题目链接:https://www.jisuanke.com/contest/870
题意:
直角坐标系上有两个三角形,它们都超某个方向匀速移动,问它们会不会在某个时候相碰
输入两行。每一行前6个数为三角形三个点坐标,后两个数dx, dy表示点(x, y)在单位时间后移动到(x+dx, y+dy)
思路:
将两个三角形的速度相减,这样问题就简化为其中一个三角形原地不动,问另一个三角形是否会碰到第二个三角形
对于移动的三角形暴力每个点,对于每个点暴力不动三角形的每条边,判断这个点在移动时是否会穿过这条边即可
具体怎么判断,有一个比较好理解的方法:
设动点为(x, y),线段两个端点为(x1, y1)和(x2, y2) (x1<=x2),dx和dy为动点的单位移动距离,t为时间
将线段转化成点斜式方程:y-y1=k(x-x1),k为斜率,然后将(x+t*dx, y+t*dy)带入点斜式方程求出t
若t>0,且此时x1<=x+t*dx<=x2,那么说明会相交,否则不会
中间注意特判分母为0的情况
补:其实这样是错的,我忘了两个三角形都要作为不动三角形判定一次才对,因为可能一个三角形很大一个三角形很小。。。感谢评论区dalao提醒
#include<stdio.h>
#include<math.h>
#include<algorithm>
using namespace std;
typedef struct
{
double x1, y1;
double x2, y2;
double x3, y3;
}Res;
Res A, B;
double Jud(double x, double y, double dx, double dy, double x1, double y1, double x2, double y2)
{
double t, ex, ey, k;
if(x1==x2)
{
if(dx==0)
{
if(x!=x1)
return 0;
t = 0;
}
else
{
t = (x1-x)/dx;
if(t<0)
return 0;
}
if(y1>y2)
swap(y1, y2);
if(y+t*dy<y1 || y+t*dy>y2)
return 0;
return 1;
}
else
{
k = (y1-y2)/(x1-x2);
if(fabs(k*dx-dy)<=1e-8)
{
if((y-y1)!=k*(x-x1))
return 0;
t = 0;
}
else
{
t = (y-y1+k*x1-k*x)/(k*dx-dy);
if(t<0)
return 0;
}
x += t*dx, y += t*dy;
if(x1>x2)
swap(x1, x2);
if(x<x1 || x>x2)
return 0;
return 1;
}
}
int main(void)
{
double T, ok, x, y, dx, dy;
int cas = 1;
scanf("%lf", &T);
while(T--)
{
ok = 0;
scanf("%lf%lf%lf%lf%lf%lf%lf%lf", &A.x1, &A.y1, &A.x2, &A.y2, &A.x3, &A.y3, &dx, &dy);
scanf("%lf%lf%lf%lf%lf%lf%lf%lf", &B.x1, &B.y1, &B.x2, &B.y2, &B.x3, &B.y3, &x, &y);
dx -= x, dy -= y;
ok = max(ok, Jud(A.x1, A.y1, dx, dy, B.x1, B.y1, B.x2, B.y2));
ok = max(ok, Jud(A.x1, A.y1, dx, dy, B.x1, B.y1, B.x3, B.y3));
ok = max(ok, Jud(A.x1, A.y1, dx, dy, B.x2, B.y2, B.x3, B.y3));
ok = max(ok, Jud(A.x2, A.y2, dx, dy, B.x1, B.y1, B.x2, B.y2));
ok = max(ok, Jud(A.x2, A.y2, dx, dy, B.x1, B.y1, B.x3, B.y3));
ok = max(ok, Jud(A.x2, A.y2, dx, dy, B.x2, B.y2, B.x3, B.y3));
ok = max(ok, Jud(A.x3, A.y3, dx, dy, B.x1, B.y1, B.x2, B.y2));
ok = max(ok, Jud(A.x3, A.y3, dx, dy, B.x1, B.y1, B.x3, B.y3));
ok = max(ok, Jud(A.x3, A.y3, dx, dy, B.x2, B.y2, B.x3, B.y3));
if(ok==1)
printf("Case #%d: YES\n", cas++);
else
printf("Case #%d: NO\n", cas++);
}
return 0;
}