题目要求判断一条线段和一个矩形是否相交,或者是否在矩形里面(题目好像没说?)
思路就是直接暴力判断和矩形四条边是否相交,和线段的坐标是否在矩形的坐标范围即可。
然后题目的数据,(xleft,ytop) 和 (xright,ybottom)不是按顺序给出的,需要自己判断下顺序。
#include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> using namespace std; #define inf (0x3f3f3f3f) typedef long long int LL; #include <iostream> #include <sstream> #include <vector> #include <set> #include <map> #include <queue> #include <string> const int maxn = 5000+20; struct coor { double x,y; coor(){} coor(double xx,double yy):x(xx),y(yy){} double operator ^(coor rhs) const //计算叉积(向量积) { return x*rhs.y - y*rhs.x; } coor operator -(coor rhs) const //坐标相减,a-b得到向量ba { return coor(x-rhs.x,y-rhs.y); } double operator *(coor rhs) const //数量积 { return x*rhs.x + y*rhs.y; } }a,b; struct Line { coor point1,point2; Line(){} Line(coor xx,coor yy):point1(xx),point2(yy){} }line[maxn],seg; const double eps = 1e-14; bool same (double a,double b) { return fabs(a-b)<eps; } bool OnSegment (coor a,coor b,coor c) //判断点C是否在线段ab上 { double min_x = min(a.x,b.x), min_y = min(a.y,b.y); double max_x = max(a.x,b.x), max_y = max(a.y,b.y); if (c.x>=min_x && c.x<=max_x && c.y>=min_y && c.y<=max_y) return true; else return false; } bool SegmentIntersect (coor a,coor b,coor c,coor d) { double d1 = (b-a)^(d-a); //direction(a,b,d);以a为起点,计算ab和ab的叉积 double d2 = (b-a)^(c-a); double d3 = (d-c)^(a-c); double d4 = (d-c)^(b-c); if (d1*d2<0 && d3*d4<0) return true; else if (same(d1,0) && OnSegment(a,b,d)) return true; else if (same(d2,0) && OnSegment(a,b,c)) return true; else if (same(d3,0) && OnSegment(c,d,a)) return true; else if (same(d4,0) && OnSegment(c,d,b)) return true; else return false; } void work () { scanf("%lf%lf%lf%lf",&seg.point1.x,&seg.point1.y,&seg.point2.x,&seg.point2.y); scanf("%lf%lf%lf%lf",&a.x,&a.y,&b.x,&b.y); if (a.x > b.x) swap(a.x,b.x); if (a.y < b.y) swap(a.y,b.y); line[1] = Line(a,coor(b.x,a.y)); line[2] = Line(coor(a.x,b.y),b); line[3] = Line(a,coor(a.x,b.y)); line[4] = Line(coor(b.x,a.y),b); for (int i=1;i<=4;++i) { if (SegmentIntersect(seg.point1,seg.point2,line[i].point1,line[i].point2)) { printf ("T "); return ; } } if (seg.point1.x>=a.x&&seg.point1.x<=b.x&&seg.point2.x>=a.x&&seg.point2.x<=b.x &&seg.point1.y>=b.y&&seg.point1.y<=a.y&&seg.point2.y>=b.y&&seg.point2.y<=a.y) { printf ("T "); return ; } printf ("F "); return ; } int main() { #ifdef local freopen("data.txt","r",stdin); #endif int t; cin>>t; while(t--) work(); return 0; }
然而这题应该用判断点在多边形里比较好
#include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> using namespace std; #define inf (0x3f3f3f3f) typedef long long int LL; #include <iostream> #include <sstream> #include <vector> #include <set> #include <map> #include <queue> #include <string> const int maxn = 5000+20; struct coor { double x,y; coor(){} coor(double xx,double yy):x(xx),y(yy){} double operator ^(coor rhs) const //计算叉积(向量积) { return x*rhs.y - y*rhs.x; } coor operator -(coor rhs) const //坐标相减,a-b得到向量ba { return coor(x-rhs.x,y-rhs.y); } double operator *(coor rhs) const //数量积 { return x*rhs.x + y*rhs.y; } }a,b,liu[maxn]; struct Line { coor point1,point2; Line(){} Line(coor xx,coor yy):point1(xx),point2(yy){} }line[maxn],seg; const double eps = 1e-14; bool same (double a,double b) { return fabs(a-b)<eps; } bool OnSegment (coor a,coor b,coor c) //判断点C是否在线段ab上 { double min_x = min(a.x,b.x), min_y = min(a.y,b.y); double max_x = max(a.x,b.x), max_y = max(a.y,b.y); if (c.x>=min_x && c.x<=max_x && c.y>=min_y && c.y<=max_y) return true; else return false; } bool SegmentIntersect (coor a,coor b,coor c,coor d) { double d1 = (b-a)^(d-a); //direction(a,b,d);以a为起点,计算ab和ab的叉积 double d2 = (b-a)^(c-a); double d3 = (d-c)^(a-c); double d4 = (d-c)^(b-c); if (d1*d2<0 && d3*d4<0) return true; else if (same(d1,0) && OnSegment(a,b,d)) return true; else if (same(d2,0) && OnSegment(a,b,c)) return true; else if (same(d3,0) && OnSegment(c,d,a)) return true; else if (same(d4,0) && OnSegment(c,d,b)) return true; else return false; } bool PointInPolygon (coor p[],int n,coor cmp) { //思路:求解y=cmp.y与多边形一侧有多少个交点,奇数就在里面,偶数就在外面,cmp在边上是不行的 int cnt = 0; //记录单侧有多少个交点,这里的p[],必须有顺序 for (int i=1;i<=n;++i) { int t = (i+1)>n ? 1:(i+1); //下标为1要这样 coor p1=p[i],p2=p[t]; if (cmp.y >= max(p1.y,p2.y)) continue;//交点在延长线上和在凸顶点都不要 if (cmp.y < min(p1.y,p2.y)) continue;//交点在凹顶点上就要,这里没取等 if (same(p1.y,p2.y)) continue; //与cmp.y是平行的 double x = (cmp.y-p1.y)*(p1.x-p2.x)/(p1.y-p2.y) + p1.x; //求交点 p1.y != p2.y不会除0错误 if (x>cmp.x) cnt++;//只统计一侧的交点 } return cnt&1; } void work () { scanf("%lf%lf%lf%lf",&seg.point1.x,&seg.point1.y,&seg.point2.x,&seg.point2.y); scanf("%lf%lf%lf%lf",&a.x,&a.y,&b.x,&b.y); if (a.x > b.x) swap(a.x,b.x); if (a.y < b.y) swap(a.y,b.y); line[1] = Line(a,coor(b.x,a.y)); line[2] = Line(coor(a.x,b.y),b); line[3] = Line(a,coor(a.x,b.y)); line[4] = Line(coor(b.x,a.y),b); liu[1]=a; liu[2]=coor(b.x,a.y); liu[3]=b; liu[4]=coor(a.x,b.y); for (int i=1;i<=4;++i) { if (SegmentIntersect(seg.point1,seg.point2,line[i].point1,line[i].point2)) { printf ("T "); return ; } } if (PointInPolygon(liu,4,seg.point1)&&PointInPolygon(liu,4,seg.point2)) { printf ("T "); return ; } printf ("F "); return ; } int main() { #ifdef local freopen("data.txt","r",stdin); #endif int t; cin>>t; while(t--) work(); return 0; }