2017 ACM-ICPC乌鲁木齐网络赛 B. Out-out-control cars(几何)

题目链接: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;
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值