http://poj.org/problem?id=1410
这道题搞了我好长时间啊,最后发现原来是原来的模板有问题,原来的模板中在判断线段相交的时候没有考虑线段共线且一个线段的一端点在另一条线段上这种情况,后来改了一
下,才过了。而且这道题要注意线段和矩形相交的定义,矩形包括四条边和中间的矩形区域,所以如果线段在矩形内部,也算是线段和矩形相交。
代码(别看代码长,全是模板!):
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
struct point
{
double x,y;
}rect[4],line[2];
double xl,xr,yt,yb,xs,xe,ys,ye;
double min(double x,double y)
{
if(x>y) return y;
return x;
}
double max(double x,double y)
{
if(x>y) return x;
return y;
}
//判断double型的正数、负数和0,分别相应的返回1、-1和0
int dblcmp(double x)
{
if(x==0) return 0;
return (x>0)?1:-1;
}
//点积
double dot(double x1,double y1,double x2,double y2)
{
return x1*x2+y1*y2;
}
//求a点是不是在线段bc上,>0不在,=0与端点重合,<0在。
int point_on_line(point a,point b,point c)
{
return dblcmp(dot(b.x-a.x,b.y-a.y,c.x-a.x,c.y-a.y));
}
//计算叉积
double det(double x1,double y1,double x2,double y2)
{return x1*y2-x2*y1;}
//计算a,b,c三点的叉积,判断a,b,c三点的位置关系
double cross(point a,point b,point c)
{return det(b.x-a.x,b.y-a.y,c.x-a.x,c.y-a.y);}
//判断线段是否相交,相交为true,不相交为false
int segcross(point a,point b,point c,point d)
{
point p;
int d1,d2,d3,d4;
d1=dblcmp(cross(a,b,c));
d2=dblcmp(cross(a,b,d));
d3=dblcmp(cross(c,d,a));
d4=dblcmp(cross(c,d,b));
//规范相交
if ((d1^d2)==-2 && (d3^d4)==-2) return 1;
//不规范相交,就是两线段共线,并且一条线段的一段在另一条线段上
if (d1==0 && point_on_line(c,a,b)<=0) {p=c;return 0;}
if (d2==0 && point_on_line(d,a,b)<=0) {p=d;return 0;}
if (d3==0 && point_on_line(a,c,d)<=0) {p=a;return 0;}
if (d4==0 && point_on_line(b,c,d)<=0) return 0;
//如果不相交
return -1;
}
int main()
{
double x1,y1,x2,y2;
int n;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%lf%lf%lf%lf%lf%lf%lf%lf",&xs,&ys,&xe,&ye,&x1,&y1,&x2,&y2);
xl=min(x1,x2),xr=max(x1,x2);
yt=max(y1,y2),yb=min(y1,y2);
if(min(xs,xe)>=xl&&min(ys,ye)>=yb&&max(xs,xe)<=xr&&max(ys,ye)<=yt)
{
printf("T\n");
continue;
}
line[0].x=xs,line[0].y=ys;
line[1].x=xe,line[1].y=ye;
rect[0].x=xl,rect[0].y=yt;
rect[1].x=xl,rect[1].y=yb;
rect[2].x=xr,rect[2].y=yb;
rect[3].x=xr,rect[3].y=yt;
bool flag=0;
if(segcross(line[0],line[1],rect[0],rect[1])!=-1) flag=1;
else if(segcross(line[0],line[1],rect[1],rect[2])!=-1) flag=1;
else if(segcross(line[0],line[1],rect[2],rect[3])!=-1) flag=1;
else if(segcross(line[0],line[1],rect[3],rect[0])!=-1) flag=1;
if(flag) printf("T\n");
else printf("F\n");
}
return 0;
}