LightOJ--1323 Billiard Balls (数学题)

题目链接:http://lightoj.com/volume_showproblem.php?problem=1323

题意:有一个w*l(5~1e8)的桌子,有n(1~1000)个球在这个桌子上,每个球有位置(x,y)和运动方向(由NW,NE,SW,SE表示),也就是说球的运动方向都是斜向的,最后要求每个球在运动了k(1~1e8)秒后的位置,(一秒的运动是x,y都变化1)球运动的时候会相撞,也会撞到桌子边缘,题目给出不同情况下撞击后的运动方向。

分析:由于之前看过一题蚂蚁爬木棍的题目(紫书上的),看到题目我便没有再去考虑球和球的撞击问题,由于两球撞击后可以看作两个球按原来的方向运动只是序号换了一下而已,所以不用考虑这个问题了,

接下来就是k秒后的位置了,这本来是很简单的,但是状态不好,画图画了好久,其实只要将x和y分开看就好了,然后就发现运动是有周期的,那在算之前要把秒数先%一下,具体的规律读者可以按代码模拟和推一下

#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
#define INF 0x3f3f3f3f 
#define LL long long

struct node
{
    int x;
    int y;
}a[1005];
bool cmp(node a,node b)
{
    if(a.x==b.x)
        return a.y<b.y;
    return a.x<b.x;
}
int up(int n,int x,int k)//n是x或者y,x是长或者宽,k是秒数,这里这么做是为了让代码看上去好一些
{
    int tmp=k%(2*x);//先余一个周期
    if(tmp>(x-n))
    {
        if((tmp-x+n)>=x)
            n=tmp-x-x+n;
        else
            n=2*x-tmp-n;
    }
    else
        n+=tmp;
    return n;
}
int down(int n,int x,int k)
{
    int tmp=k%(2*x);
    if(tmp>n)
    {
        if(tmp-n>x)
            n=2*x-tmp+n;
        else
            n=tmp-n;
    }
    else
        n-=tmp;
    return n;
}
int main()
{
    ios::sync_with_stdio(false);
    int l,w,n,k;
    int t;
    cin>>t;
    for(int i=1;i<=t;i++)
    {
        cin>>l>>w>>n>>k;
        for(int j=1;j<=n;j++)
        {
            char y,x;
            cin>>a[j].x>>a[j].y;
            cin>>y>>x;
            if(y=='N')
                a[j].y=up(a[j].y,w,k);
            if(y=='S')
                a[j].y=down(a[j].y,w,k);
            if(x=='E')
                a[j].x=up(a[j].x,l,k);
            if(x=='W')
                a[j].x=down(a[j].x,l,k);
        }
        sort(a+1,a+1+n,cmp);
        cout<<"Case "<<i<<":"<<endl;
        for(int k=1;k<=n;k++)
            cout<<a[k].x<<" "<<a[k].y<<endl;
    }    
}
原文地址:https://www.cnblogs.com/Oremix/p/7111728.html