一道简单的几何题:HDOJ5114
对于有模板和懂数学的大神来说,几何题都是水题吧
给两个点的坐标,初始化的速度方向向量为(1,1),两个点在n*m的矩阵中移动,遇到边界没有能量损失反弹前进,问这两个点是不是会在某个点相遇?求出相遇点的坐标。
几何题都得懂原理才能写
首先得明白有几种情况相遇:
1.两个点,速度方向向量互为相反,即相向而行,且x方向的差量与y方向的差量相同
2.两个点,同x轴,x轴方向向量相同,且如果能相遇,相遇点的y值在界内
3.两个点,同y轴,y轴方向向量相同,且如果能相遇,相遇点的x值在界内
所以,两个点拆成4个方向向量来做是最好的
如何模拟呢?n最大100000,矩形4条边,不妨直接暴力400000次,逐个以公式带入判断会不会相同
具体细节看代码
//第一个点坐标为(x1,y1)
//第一个点方向向量为(fx11,fx12)
//同理第二个点
//注意细节,y1这个变量在math.h中有过定义
//平时写程序尽量避免使用
//G++和C++编译器有区别
//在不怕TLE的情况下用G++更好
int x1,y1,x2,y2,t,fx11,fx12,fx21,fx22,Move,n,m;
double ansx,ansy;
void change_dir(){
//第一个点到达最右边并且x方向上速度向右
//第一个点到达最左边并且x方向上速度向左
if ((x1==n&&fx11>0)||(x1==0&&fx11<0)) fx11=-fx11;
//之后同理
if ((y1==m&&fx12>0)||(y1==0&&fx12<0)) fx12=-fx12;
if ((x2==n&&fx21>0)||(x2==0&&fx21<0)) fx21=-fx21;
if ((y2==m&&fx22>0)||(y2==0&&fx22<0)) fx22=-fx22;
}
int main(){
//input;
int i;
scanf("%d",&t);
for(int Case=1;Case<=t;Case++){
scanf("%d%d%d%d%d%d",&n,&m,&x1,&y1,&x2,&y2);
fx11=fx12=fx21=fx22=1;
//如果有点一开始就在边界上而且恰好往边界方向有分速度
//那么刚出发时就需要对速度矢量进行更改
change_dir();
//n最大为100000,考虑到矩形有4条边
//相当于把边界上的所有点枚举一遍
for(i=1;i<=410000;i++){
//Case1:两个点迎面相遇
//条件为:两边方向迎面,而且x和y轴上相差的距离相等
if (abs(x1-x2)==abs(y1-y2)&&(x2-x1)/fx11>0&&(y2-y1)/fx12>0
&&(x1-x2)/fx21>0&&(y1-y2)/fx22>0){
ansx=(x1+x2)/2.0;
ansy=(y1+y2)/2.0;
break;
}
//Case2:两个点在同一纵轴上
//那么速度方向需要时反的,并且在相遇时候不能够走出界
if (x1==x2&&(y2-y1)/fx12>0&&(y1-y2)/fx22>0&&fx11==fx21
&&(x1+fx11*abs(y2-y1)/2.0>=0)&&(x1+fx11*abs(y2-y1)/2.0<=n)){
//在同一纵轴上,y坐标取平均值为相遇点
//根据y的变化算出两个点的运动时间,进而求x
ansx=x1+fx11*abs(y2-y1)/2.0;
ansy=(y1+y2)/2.0;
break;
}
//Case3:同理Case2,两个点在同一横轴上
if (y1==y2&&(x2-x1)/fx11>0&&(x1-x2)/fx21>0&&fx12==fx22
&&(y1+fx12*abs(x2-x1)/2.0>=0)&&(y1+fx12*abs(x2-x1)/2.0<=m)){
ansx=(x1+x2)/2.0;
ansy=y1+fx12*abs(x2-x1)/2.0;
break;
}
//如果三种Case都没有发生
//那么肯定会遇到某个点在某个方向上撞墙的情况
//所以找到从现在到最近撞墙的时间
//进一步修改点的位置和运动方向矢量
//因为速度大小是(1,1)
//所以直接根据距离算时间就好,判断一下运动方向
if (fx11>0) Move=n-x1;
else Move=x1;
if (fx12>0) Move=min(Move,m-y1);
else Move=min(Move,y1);
if (fx21>0) Move=min(Move,n-x2);
else Move=min(Move,x2);
if (fx22>0) Move=min(Move,m-y2);
else Move=min(Move,y2);
//到达边界之后马上修改运动方向
x1+=Move*fx11;
y1+=Move*fx12;
x2+=Move*fx21;
y2+=Move*fx22;
change_dir();
}
printf("Case #%d:\n",Case);
if (i==410001){
puts("Collision will not happen.");
continue;
}
else printf("%.1lf %.1lf\n",ansx,ansy);
}
return 0;
}