题意:给定一条线段的两个端点,再给定矩形顶点的两个横坐标和两个总坐标(矩形的边与坐标轴平行)。求线段和矩形是否有公共点(矩形是实心的)
思路:首先题意确实比较容易出现歧义。需要注意两点:1、矩形是实心的(The rectangle consists of four straight lines and the area in between),所以如果线段完全在矩形内部也算相交;2、给定的矩形坐标并不是按照矩形的端点坐标给出的,而需要自行判断。
那么所需判断的就是给定线段和矩形四条边是否相交,如果不相交,再判断线段是否在矩形内部。
#include <stdio.h>
#include <string.h>
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
#define eps 1e-10
typedef struct point{
int x,y;
}P;
P p[4],s,t;
int n,T;
double multi(P a,P b,P c){
return (b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x);
}
int inter(P x,P y,P s,P t){//判断线段xy和线段st是否相交
double a,b,c,d;
if(min(x.x,y.x)>max(s.x,t.x) || min(x.y,y.y)>max(s.y,t.y) ||
min(s.x,t.x)>max(x.x,y.x) || min(s.y,t.y)>max(x.y,y.y))
return 0;
a = multi(x,y,s);
b = multi(x,y,t);
c = multi(s,t,x);
d = multi(s,t,y);
return a*b<eps && c*d<eps;
}
int in(P a){//判断点a是否在矩形内部
return a.x>=p[0].x&&a.x<=p[2].x&&a.y>=p[0].y&&a.y<=p[2].y;
}
int main(){
freopen("a.txt","r",stdin);
scanf("%d",&T);
while(T--){
int i,j,flag=0;
scanf("%d %d %d %d",&s.x,&s.y,&t.x,&t.y);
scanf("%d %d %d %d",&p[0].x,&p[0].y,&p[2].x,&p[2].y);
if(p[0].x > p[2].x){
int temp = p[0].x;
p[0].x = p[2].x;
p[2].x = temp;
}
if(p[0].y > p[2].y){
int temp = p[0].y;
p[0].y = p[2].y;
p[2].y = temp;
}//使得p[0]存放矩形的左下点,p[2]存放右上点
p[1].x = p[2].x;
p[1].y = p[0].y;
p[3].x = p[0].x;
p[3].y = p[2].y;
for(i = 0;i<4;i++)
if(inter(p[i],p[(i+1)%4],s,t)){//分别判断线段和矩形边是否相交
flag = 1;
break;
}
if(!flag && (in(s) || in(t)))//判断线段端点是否在矩形内部
flag = 1;
if(flag)
printf("T\n");
else
printf("F\n");
}
return 0;
}