hdu 5114 Collision

Collision

Time Limit: 15000/15000 MS (Java/Others)    Memory Limit: 512000/512000 K (Java/Others)
Total Submission(s): 1645    Accepted Submission(s): 442


Problem Description
Matt is playing a naive computer game with his deeply loved pure girl.

The playground is a rectangle with walls around. Two balls are put in different positions inside the rectangle. The balls are so tiny that their volume can be ignored. Initially, two balls will move with velocity (1, 1). When a ball collides with any side of the rectangle, it will rebound without loss of energy. The rebound follows the law of refiection (i.e. the angle at which the ball is incident on the wall equals the angle at which it is reflected).

After they choose the initial position, Matt wants you to tell him where will the two balls collide for the first time.
Input
The first line contains only one integer T which indicates the number of test cases.

For each test case, the first line contains two integers x and y. The four vertices of the rectangle are (0, 0), (x, 0), (0, y) and (x, y). (1 ≤ x, y ≤ 105)

�The next line contains four integers x1, y1, x2, y2. The initial position of the two balls is (x1, y1) and (x2, y2). (0 ≤ x1, x2 ≤ x; 0 ≤ y1, y2 ≤ y)
Output
For each test case, output “Case #x:” in the first line, where x is the case number (starting from 1).

In the second line, output “Collision will not happen.” (without quotes) if the collision will never happen. Otherwise, output two real numbers xc and yc, rounded to one decimal place, which indicate the position where the two balls will first collide.
Sample Input
3
10 10
1 1 9 9
10 10
0 5 5 10
10 10
1 0 1 10
Sample Output
Case #1:
6.0 6.0
Case #2:
Collision will not happen.
Case #3:
6.0 5.0
题目大意:两个球在一个矩形里面做完全弹性碰撞的运动,位置给出,速度恒为(1,1)。
问它们会不会碰撞到一起,会的话第一次碰撞在哪个点?
思路:对速度进行正交分解。为了避免小数,所有数据*2。
分情况讨论:
1、如果两个点重合,直接输出那个点。
2、如果横坐标相同讨论纵坐标的情况。
3、如果纵坐标相同讨论横坐标的情况
4、都不相同。那么可列出两个同余方程组来
假如tx代表在x轴上运动了tx时间两点横坐标相同。
那么有(假设x1>x2)  n-(x1+tx-n)=x2+tx 。 即 tx=n-(x1+x2)/2 ;(这也是为什么数据都乘2的原因)
同理我们可以列得y轴上的方程。
扩展欧几里得算法求解同余方程。
(ps:写这题目一定要仔细!!!因为把m写成了n,弄得wa了好多遍,查了一个多小时的bug)
繁琐的AC代码:
 1 #include<iostream>
 2 #include<stdio.h>
 3 #include<bits/stdc++.h>
 4 #define ll long long
 5 using namespace std;
 6 ll exgcd(ll a,ll b,ll &x,ll &y){
 7     if(b==0){
 8         x=1;
 9         y=0;
10         return a;
11     }
12     ll gcd=exgcd(b,a%b,x,y);
13     ll t=x;
14     x=y;
15     y=t-(a/b)*y;
16     return gcd;
17 }
18 int main(){
19     int T;
20     cin>>T;
21     for(int times=1;times<=T;times++){
22         ll n,m;
23         cin>>n>>m;
24         ll x1,x2,y1,y2;
25         cin>>x1>>y1>>x2>>y2;
26         n=2*n; m=2*m; x1=2*x1; y1=2*y1; x2=2*x2; y2=2*y2;
27         ll ansx,ansy;
28         printf("Case #%d:
",times);
29         if(x1==x2&&y1==y2){
30             ansx=x1;
31             ansy=y1;
32             printf("%.1f %.1f
",ansx/2,ansy/2);
33         }else if(x1==x2){
34             ll tb=m-(y1+y2)/2;
35             x1=(x1+tb)%(2*n);
36             y1=(y1+tb)%(2*m);
37             if(x1>n){
38                 ansx=n-(x1-n);
39             }else{
40                 ansx=x1;
41             }
42             if(y1>m){
43                 ansy=m-(y1-m);
44             }else{
45                 ansy=y1;
46             }
47             printf("%.1f %.1f
",ansx/2.0,ansy/2.0);
48         }else if(y1==y2){
49             ll ta=n-(x1+x2)/2;
50             x1=(x1+ta)%(2*n);
51             y1=(y1+ta)%(2*m);
52             if(x1>n){
53                 ansx=n-(x1-n);
54             }else{
55                 ansx=x1;
56             }
57             if(y1>m){
58                 ansy=m-(y1-m);
59             }else{
60                 ansy=y1;
61             }
62             printf("%.1f %.1f
",ansx/2.0,ansy/2.0);
63         }else{
64             ll ta=n-(x1+x2)/2;
65             ll tb=m-(y1+y2)/2;
66             ll x,y,gcd,c;
67             c=tb-ta;
68             gcd=exgcd(n,m,x,y);
69             if(c%gcd!=0){
70                 printf("Collision will not happen.
");
71             }else{
72                 ll r=m/gcd;
73                 x=((x*c/gcd)%r+r)%r;
74                 ll t=ta+x*n;
75                 ll tmpx,tmpy;
76                 tmpx=(x1+t)%(2*n);
77                 tmpy=(y1+t)%(2*m);
78                 if(tmpx>n){
79                     tmpx=n-(tmpx-n);
80                 }
81                 if(tmpy>m){
82                     tmpy=m-(tmpy-m);   //就是这里!!!第二个m写成了n!!!
83                 }
84                 ansx=tmpx;
85                 ansy=tmpy;
86                 printf("%.1f %.1f
",ansx/2.0,ansy/2.0);
87             }
88         }
89     }
90     return 0;
91 }
简单的代码来源:https://www.cnblogs.com/TenderRun/p/5943453.html
 1 /*
 2 愣是照着这个代码查了半天都没查出之前代码为什么wa,后面还是不经意间发现的!!!
 3 如果一开始就按这个代码写,讨论情况的时候会简单很多。orz
 4 */
 5 #include <iostream>
 6 #include <cstring>
 7 #include <cstdio>
 8 using namespace std;
 9 typedef long long LL;
10 LL ta,tb,x,y,tim;
11 int T,cas,n,m,x1,y1,x2,y2;
12 LL Exgcd(LL a,LL b,LL&x,LL&y){
13     if(b==0){x=1,y=0;return a;}
14     LL ret=Exgcd(b,a%b,y,x);
15     y-=a/b*x;return ret;
16 }
17 int main(){
18     scanf("%d",&T);
19     while(T--){
20         scanf("%d%d%d%d%d%d",&n,&m,&x1,&y1,&x2,&y2);
21         n*=2;m*=2;x1*=2;y1*=2;x2*=2;y2*=2;
22         ta=n-(x1+x2)/2;tb=m-(y1+y2)/2;
23         printf("Case #%d:
",++cas);tim=-1;
24         if(x1==x2&&y1==y2)tim=0;
25         if(x1!=x2&&y1==y2)tim=ta;
26         if(x1==x2&&y1!=y2)tim=tb;
27         if(x1!=x2&&y1!=y2){
28             LL d=Exgcd(n,m,x,y);
29             if((tb-ta)%d==0){
30                 x=(tb-ta)/d*x;
31                 x=(x%(m/d)+m/d)%(m/d);
32                 tim=ta+n*x;
33             }
34         }
35         if(tim==-1)
36             puts("Collision will not happen.");
37         else{
38             x1=(x1+tim)%(2*n);y1=(y1+tim)%(2*m);
39             if(x1>n)x1=2*n-x1;if(y1>m)y1=2*m-y1;
40             printf("%.1f %.1f
",x1/2.0,y1/2.0);
41         }    
42     }
43     return 0;
44 }
原文地址:https://www.cnblogs.com/ISGuXing/p/8797627.html