这个模型是可以转化的。。先去调边界限制,那么2个球会往同一方向平行移动,事实上他们的坐标可以对称到(n,m)内的范围来,如下图:
编号相同的区域可以直接移回来。。为什么可以这么看呢。。因为每碰撞一次相当于一次镜面反射。。
然后如果x相同,2个点的中点碰到纵向边界即可,y相同同理
然后就是讨论xy各不相同的情况。。很容易想到,只有他们的中点在(pn,qm)处,即矩形的顶点上时,他们的位置才会重合。。
那么由于他们以(1,1)速度移动,因此可以用x和y的坐标差来列方程,即
其中(x0,y0)为中点坐标
解出来后把他移回2n,2m内然后去对称一下就出来了。。
/**
* ┏┓ ┏┓
* ┏┛┗━━━━━━━┛┗━━━┓
* ┃ ┃
* ┃ ━ ┃
* ┃ > < ┃
* ┃ ┃
* ┃... ⌒ ... ┃
* ┃ ┃
* ┗━┓ ┏━┛
* ┃ ┃ Code is far away from bug with the animal protecting
* ┃ ┃ 神兽保佑,代码无bug
* ┃ ┃
* ┃ ┃
* ┃ ┃
* ┃ ┃
* ┃ ┗━━━┓
* ┃ ┣┓
* ┃ ┏┛
* ┗┓┓┏━┳┓┏┛
* ┃┫┫ ┃┫┫
* ┗┻┛ ┗┻┛
*/
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
#include<cmath>
#include<map>
#include<stack>
#include<set>
#include<bitset>
#include<stdlib.h>
#include<assert.h>
#define inc(i,l,r) for(int i=l;i<=r;i++)
#define dec(i,l,r) for(int i=l;i>=r;i--)
#define link(x) for(edge *j=h[x];j;j=j->next)
#define mem(a) memset(a,0,sizeof(a))
#define ll long long
#define eps 1e-8
#define succ(x) (1<<x)
#define lowbit(x) (x&(-x))
#define sqr(x) ((x)*(x))
#define mid (x+y>>1)
#define NM 55
#define nm 50005
#define pi 3.1415926535897931
const ll inf=1e9+7;
using namespace std;
ll read(){
ll x=0,f=1;char ch=getchar() ;
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
return f*x;
}
ll n,m,x,y,_x,_y,__x,__y,p,q;
int ca;
ll exgcd(ll n,ll m,ll&p,ll&q){
if(m==0){p=1;q=0;return n;}
ll t=exgcd(m,n%m,q,p);
q=q-n/m*p;return t;
}
int main(){
int _=read();while(_--){
printf("Case #%d:\n",++ca);
n=read()<<1;m=read()<<1;
x=read()<<1;y=read()<<1;_x=read()<<1;_y=read()<<1;
if(x==_x){
ll t=(y+_y)/2;
t=m-t;x+=t;y+=t;_x+=t;_y+=t;
if(y<_y)printf("%.1lf %.1lf\n",x/2.0,y/2.0);
else printf("%.1lf %.1lf\n",_x/2.0,_y/2.0);
continue;
}else if(y==_y){
ll t=(x+_x)/2;
t=n-t;x+=t;y+=t;_x+=t;_y+=t;
if(y<_y)printf("%.1lf %.1lf\n",x/2.0,y/2.0);
else printf("%.1lf %.1lf\n",_x/2.0,_y/2.0);
continue;
}
__x=x;__y=y;x=(x+_x)/2;y=(y+_y)/2;
ll t=exgcd(n,m,p,q);
if(abs(x-y)%t){printf("Collision will not happen.\n");continue;}
p*=(x-y)/t;q*=(x-y)/t;q=-q;
ll tmp=min(p/(m/t),q/(n/t));
p-=tmp*(m/t);q-=tmp*(n/t);
if(p<=0||q<=0)p+=m/t,q+=n/t;
t=p*n-x;_x+=t;_y+=t;__x+=t;__y+=t;
_x%=2*n;_y%=2*m;__x%=2*n;__y%=2*m;
if(_y>m)_y=2*m-_y;
if(_x>n)_x=2*n-_x;
printf("%.1lf %.1lf\n",_x/2.0,_y/2.0);
}
return 0;
}
CollisionTime Limit: 15000/15000 MS (Java/Others) Memory Limit: 512000/512000 K (Java/Others)Total Submission(s): 1749 Accepted Submission(s): 471 Problem Description Matt is playing a naive computer game with his deeply loved pure girl.
Input The first line contains only one integer T which indicates the number of test cases.
Output For each test case, output “Case #x:” in the first line, where x is the case number (starting from 1).
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 Hint In first example, two balls move from (1, 1) and (9, 9) both with velocity (1, 1), the ball starts from (9, 9) will rebound at point (10, 10) then move with velocity (−1, −1). The two balls will meet each other at (6, 6).
Source 2014ACM/ICPC亚洲区北京站-重现赛(感谢北师和上交)
Recommend liuyiding
|