题意:给定一条线段的两个端点,再给定矩形顶点的两个横坐标和两个总坐标(矩形的边与坐标轴平行)。求线段和矩形是否有公共点(矩形是实心的)
思路:首先题意确实比较容易出现歧义。需要注意两点: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; }