poj 1410

给定一个矩形和一条线段,求线段能否交矩形,线段与矩形的边或矩形内部有交点即为交。很简单的一道判断线段相交的题目,不过要正确理解题目意思:相交要包括矩形的内部,即线段在矩形内部也是True。(The rectangle consists of four straight lines and the area in between.)题目说的左上、右下并非座标中的位置,数据给的点也会是左下、右上!!!(The terms top left and bottom right do not imply any ordering of coordinates. )
刚开始写的代码,一直错,后来终于发现,判断线段相交的模板有问题,亏我用这个模板ac了好几道题,通过这道题发现原来我写的模板是有问题的。
/*9 1 9 2 4 3 9 6
9 2 9 1 4 3 9 6
F F */ 这组测试样例通不过
#include<stdio.h>
struct node
{
	double x,y;
};
struct pp
{
	node a,b;
}line[10];
double multi(node a,node b,node c)
{
	return ((a.x-c.x)*(b.y-c.y)-(a.y-c.y)*(b.x-c.x));
}
double min(double a,double b)
{
	return a<b?a:b;
}
double max(double a,double b)
{
	return a>b?a:b;
}
int main()
{
	double n1,n2,n3,n4,t1,t2,t3,t4,a,b,c,d;
	int n,i,j;
	scanf("%d",&n);
	for(i=1;i<=n;i++)
	{
		scanf("%lf%lf%lf%lf",&line[0].a.x,&line[0].a.y,&line[0].b.x,&line[0].b.y);
		scanf("%lf%lf%lf%lf",&a,&b,&c,&d);
		n1=max(a,c);n2=min(a,c);
		n3=max(b,d);n4=min(b,d);
		line[1].a.x=n2;line[1].a.y=n4;line[1].b.x=n2;line[1].b.y=n3;
		line[2].a.x=n2;line[2].a.y=n3;line[2].b.x=n1;line[2].b.y=n3;
		line[3].a.x=n1;line[3].a.y=n3;line[3].b.x=n1;line[3].b.y=n4;
		line[4].a.x=n1;line[4].a.y=n4;line[4].b.x=n2;line[4].b.y=n4;
		for(j=1;j<=4;j++)
		{
			t1=multi(line[j].a,line[j].b,line[0].a);
			t2=multi(line[j].a,line[j].b,line[0].b);
			t3=multi(line[0].a,line[0].b,line[j].a);
			t4=multi(line[0].a,line[0].b,line[j].b);
			if(t1*t2<=0&&t3*t4<=0)
				break;
		}
		if(j<=4)
			printf("T\n");
		else
		{
			a=line[0].a.x;b=line[0].a.y;c=line[0].b.x;d=line[0].b.y;
			if(a>n2&&a<n1&&c>n2&&c<n1&&b>n4&&b<n3&&d>n4&&d<n3)
				printf("T\n");
			else
				printf("F\n");
		}
	}
	
	return 0;
}

正确代码:
#include<stdio.h>
#include<math.h>
struct node
{
	double x,y;
};
struct pp
{
	node a,b;
}line[10];
double min(double a,double b)
{
	return a<b?a:b;
}
double max(double a,double b)
{
	return a>b?a:b;
}
double multi(node p0, node p1, node p2)
{
    return ( p1.x - p0.x )*( p2.y - p0.y )-( p2.x - p0.x )*( p1.y - p0.y );
}
//相交返回true,否则为false, 接口为两线段的端点
bool isIntersected(node s1,node e1, node s2,node e2)
{
    return  (max(s1.x,e1.x) >= min(s2.x,e2.x))  &&
            (max(s2.x,e2.x) >= min(s1.x,e1.x))  &&
            (max(s1.y,e1.y) >= min(s2.y,e2.y))  &&
            (max(s2.y,e2.y) >= min(s1.y,e1.y))  &&
            (multi(s1,e1,s2)*multi(s1,e1,e2)<=0) &&
            (multi(s2,e2,s1)*multi(s2,e2,e1)<=0);
}
int main()
{
	double n1,n2,n3,n4,a,b,c,d;
	int n,i,j;
	scanf("%d",&n);
	for(i=1;i<=n;i++)
	{
		scanf("%lf%lf%lf%lf",&line[0].a.x,&line[0].a.y,&line[0].b.x,&line[0].b.y);
		scanf("%lf%lf%lf%lf",&a,&b,&c,&d);
		n1=max(a,c);n2=min(a,c);
		n3=max(b,d);n4=min(b,d);
		line[1].a.x=n2;line[1].a.y=n4;line[1].b.x=n2;line[1].b.y=n3;
		line[2].a.x=n2;line[2].a.y=n3;line[2].b.x=n1;line[2].b.y=n3;
		line[3].a.x=n1;line[3].a.y=n3;line[3].b.x=n1;line[3].b.y=n4;
		line[4].a.x=n1;line[4].a.y=n4;line[4].b.x=n2;line[4].b.y=n4;
		for(j=1;j<=4;j++)
		{
		
			if(isIntersected(line[0].a,line[0].b,line[j].a,line[j].b))
				break;
		}
		if(j<=4)
			printf("T\n");
		else
		{
			a=line[0].a.x;
			b=line[0].a.y;
			c=line[0].b.x;
			d=line[0].b.y;
			if(a>n2&&a<n1&&c>n2&&c<n1&&b>n4&&b<n3&&d>n4&&d<n3)
				printf("T\n");
			else
				printf("F\n");
		}
	}
	
	return 0;
}


测试数据:
 68
4 9 11 2 1 1 7 5
11 2 4 9 1 1 7 5
12 12 24 24 19 5 25 17
4 6 15 9 1 1 11 11
19 5 25 17 12 12 24 24
0 18 8 12 1 1 11 11
2 4 4 2 1 1 11 11
-4 9 -11 2 -1 1 -7 5
-11 2 -4 9 -1 1 -7 5
-12 12 -24 24 -19 5 -25 17
-4 6 -15 9 -1 1 -11 11
-19 5 -25 17 -12 12 -24 24
0 18 -8 12 -1 1 -11 11
-2 4 -4 2 -1 1 -11 11
4 -9 11 -2 1 -1 7 -5
11 -2 4 -9 1 -1 7 -5
12 -12 24 -24 19 -5 25 -17
4 -6 15 -9 1 -1 11 -11
19 -5 25 -17 12 -12 24 -24
0 -18 8 -12 1 -1 11 -11
2 -4 4 -2 1 -1 11 -11
-4 -9 -11 -2 -1 -1 -7 -5
-11 -2 -4 -9 -1 -1 -7 -5
-12 -12 -24 -24 -19 -5 -25 -17
-4 -6 -15 -9 -1 -1 -11 -11
-19 -5 -25 -17 -12 -12 -24 -24
0 -18 -8 -12 -1 -1 -11 -11
-2 -4 -4 -2 -1 -1 -11 -11
9 1 9 2 4 3 9 6
9 2 9 1 4 3 9 6
10 3 13 3 4 3 9 6
13 3 10 3 4 3 9 6
10 6 14 6 4 3 9 6
14 6 10 6 4 3 9 6
9 7 9 10 4 3 9 6
9 10 9 7 4 3 9 6
4 7 4 10 4 3 9 6
4 10 4 7 4 3 9 6
0 6 3 6 4 3 9 6
3 6 0 6 4 3 9 6
1 3 3 3 4 3 9 6
3 3 1 3 4 3 9 6
4 0 4 2 4 3 9 6
4 2 4 0 4 3 9 6
5 3 8 5 4 3 9 6
8 5 5 3 4 3 9 6
5 3 8 3 4 3 9 6
8 3 5 3 4 3 9 6
6 4 6 5 4 3 9 6
6 5 6 4 4 3 9 6
4 3 9 6 4 3 9 6
9 6 4 3 4 3 9 6
4 3 5 4 4 3 9 6
5 4 4 3 4 3 9 6
5 3 8 3 4 3 9 6
8 3 5 3 4 3 9 6
5 3 9 3 4 3 9 6
9 3 5 3 4 3 9 6
4 4 4 5 4 3 9 6
4 5 4 4 4 3 9 6
4 3 4 5 4 3 9 6
4 5 4 3 4 3 9 6
4 3 4 6 4 3 9 6
4 6 4 3 4 3 9 6
9 2 9 5 4 3 9 6
9 5 9 2 4 3 9 6
9 2 9 7 4 3 9 6
9 7 9 2 4 3 9 6
out
F
F
F
T
T
F
T
F
F
F
T
T
F
T
F
F
F
T
T
F
T
F
F
F
T
T
F
T
F
F
F
F
F
F
F
F
F
F
F
F
F
F
F
F
T
T
T
T
T
T
T
T
T
T
T
T
T
T
T
T
T
T
T
T
T
T
T
T
   

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值