HDU 5114 Collision

题目链接:HDU-5114

题意为给一个矩形n*m,两个给定坐标的球在矩形中都以(1,1)的速度运动,碰到边界会反弹,求第一次碰撞的坐标。

思路是首先把运动分解为横向运动和纵向运动分别考虑,则变成两个追赶运动。假设\(x_2>x_1,y_2>y_1\),可以得到x坐标相同的时间为\(t_x=n - \frac{x_2-x_1}{2}-x_1+kn = n - \frac{x_1+x_2}{2}+kn \),y坐标相同时间为\(t_y=m - \frac{y_2-y_1}{2}-y_1+k'm = m - \frac{y_1+y_2}{2}+k'm \),其中 k,k' >= 0。

于是我们就可以得到\(t= m - \frac{y_1+y_2}{2}+k'm =n - \frac{x_1+x_2}{2}+kn\),变换就是我们熟悉的\(kn - k'm = (m - \frac{y_1+y_2}{2})-(n - \frac{x_1+x_2}{2})\),也就是二元一次方程求最小非负整数解。

但是这里面还有一个问题,就是方程中由于有\(\frac{y_1+y_2}{2}\)和\(\frac{x_1+x_2}{2}\),存在小数。所以我们把所有值全部提前*2,这里可以理解为所有坐标和矩形尺寸全部拉伸为原来的两倍。

于是方程变成了\(2nk - 2mk' = (2m - y_1 - y_2)-(n - x_1 - x_2)\),求解即可。

题目中还有一些需要注意的细节,比如(\(x_1=x_2 ,y_1=y_2\)),(\(x_1=x_2 ,y_1!=y_2\)),(\(x_1!=x_2 ,y_1=y_2\))三种情况,并不满足上述方程,需要特判。

代码如下:

 1 #include<cstdio>
 2 #include<set>
 3 #include<map>
 4 #include<cstring>
 5 #include<algorithm>
 6 #include<queue>
 7 #include<iostream>
 8 using namespace std;
 9 typedef long long LL;
10 
11 
12 //拓展欧几里得算法
13 //求ax+by=gcd(a,b)的一组解
14 //其他解为x=x0+kb',y=y0-ka'
15 //a'=a/gcd(a,b),b'=b/gcd(a,b)
16 LL extgcd(LL a,LL b,LL &x,LL &y)
17 {
18     LL d=a;
19     if(b!=0)
20     {
21         d=extgcd(b,a%b,y,x);
22         y-=(a/b)*x;
23     }
24     else { x=1; y=0; }
25     return d;
26 }
27 
28 //求最大公约数
29 LL gcd(LL a,LL b)
30 {
31     if(b==0) return a;
32     return gcd(b,a%b);
33 }
34 
35 
36 int main()
37 {
38 #ifdef LOCAL
39     freopen("in.txt","r",stdin);
40 #endif
41     LL t;
42     scanf("%lld",&t);
43     for(LL tt=1;tt<=t;tt++)
44     {
45         printf("Case #%lld:\n",tt);
46         LL n,m,x1,x2,y1,y2;
47         scanf("%lld%lld%lld%lld%lld%lld",&n,&m,&x1,&y1,&x2,&y2);
48         LL t2;
49         LL tx2=(2*n-x1-x2),ty2=(2*m-y1-y2);
50         if(x1==x2 && y1==y2) {printf("%.1lf %.1lf\n",1.0*x1,1.0*y1); continue;}
51         else if(x1==x2) t2=ty2;
52         else if(y1==y2) t2=tx2;
53         else
54         {
55             LL k,kk;
56             LL g=extgcd(2*n,2*m,k,kk);
57             LL tmp=ty2-tx2;
58             if(tmp%g)
59             {
60                 printf("Collision will not happen.\n");
61                 continue;
62             }
63             else
64             {
65                 k=tmp/g*k;
66                 LL mm=2*m/g;
67                 k=(k % mm + mm) % mm;
68                 t2=tx2+k*2*n;
69                 if(t2<ty2) t2+=(ty2-t2)/k*k;
70                 if(t2<ty2) t2+=k;
71             }
72         }
73         LL xx=(2*x1+t2)%(2*n);
74         LL yy=(2*y1+t2)%(2*m);
75         if(((2*x1+t2)/(2*n))%2) xx=2*n-xx;
76         if(((2*y1+t2)/(2*m))%2) yy=2*m-yy;
77         printf("%.1lf %.1lf\n",xx/2.0,yy/2.0);
78     }
79     return 0;
80 }

 

posted @ 2017-03-11 10:02  HuaZhang  阅读(414)  评论(0编辑  收藏  举报