LightOJ 1323 Billiard Balls(找规律(蚂蚁爬木棍))
题目链接:https://vjudge.net/contest/28079#problem/M
题目大意:
一个边界长为L宽为W的平面同时发射n个台球,运动K秒,台球碰到桌面及两(多)个台球相撞情况如下图所示,求K秒后这n个球的位置(要排序,依次按横纵坐标升序):
解题思路:其实跟以前的经典题蚂蚁爬木棍是一样的,总结为以下几点:
①两(多)球相撞的情况可以忽略,因为两球撞击后可以看作两个球按原来的方向运动只是序号换了一下而已,多球同理。
③碰壁时反向
②可以把横纵坐标分开计算,这样就很明了了,可以分别发现周期性的规律,比如长为L那么2L为一个周期球会回到原点,%一下再找一下2L之内的规律就好了,就不啰嗦了,代码里有。
代码:
1 #include<iostream> 2 #include<algorithm> 3 #include<cstdio> 4 using namespace std; 5 typedef long long LL; 6 const int N=1005; 7 8 struct node{ 9 int x,y; 10 }res[N]; 11 12 bool cmp(node a,node b){ 13 return a.x==b.x?a.y<b.y:a.x<b.x; 14 } 15 //规律 16 int cal(int x,int h,int t){ 17 t%=2*h; 18 if(t<h-x) 19 return x+t; 20 if(t<2*h-x) 21 return 2*h-t-x; 22 return x+t-2*h; 23 } 24 25 int main(){ 26 int T; 27 scanf("%d",&T); 28 int cas=0; 29 while(T--){ 30 int L,W,n,K; 31 scanf("%d%d%d%d",&L,&W,&n,&K); 32 for(int i=1;i<=n;i++){ 33 char s[5]; 34 int x,y; 35 scanf("%d%d%s",&x,&y,s); 36 if(s[0]=='N') 37 y=cal(y,W,K); 38 else if(s[0]=='S') 39 y=W-cal(W-y,W,K); 40 if(s[1]=='E') 41 x=cal(x,L,K); 42 else if(s[1]=='W') 43 x=L-cal(L-x,L,K); 44 res[i].x=x; 45 res[i].y=y; 46 } 47 sort(res+1,res+1+n,cmp); 48 printf("Case %d:\n",++cas); 49 for(int i=1;i<=n;i++){ 50 printf("%d %d\n",res[i].x,res[i].y); 51 } 52 } 53 } 54