题目大意:给一个凸多边形(点不是按顺序给的),然后计算给出的线段在这个凸多边形里面的长度,如果在边界不计算。
分析:WA2..WA3...WA4..WA11...WA的无话可说,总之细节一定考虑清楚,重合的时候一定是0
代码如下:
=========================================================================================================
#include<stdio.h> #include<math.h> #include<algorithm> #include<iostream> using namespace std; const int MAXN = 1007; const double EPS = 1e-14; const double FarX = 4e4+7; int Sign(double x) { if(x > EPS)return 1; if(fabs(x) < EPS)return 0; return -1; } struct point { double x, y; point(double x=0, double y=0):x(x),y(y){} point operator - (const point &t)const{ return point(x-t.x, y-t.y); } bool operator == (const point &t)const{ return Sign(x-t.x) ==0 && Sign(y-t.y) == 0; } double operator ^(const point &t)const{ return x*t.y - y*t.x; } double operator *(const point &t)const{ return x*t.x + y*t.y; } }; double Dist(point t1, point t2) { return sqrt((t1-t2)*(t1-t2)); } struct segment { point S, E; double a, b, c;///ax + by = c; segment(point S=0, point E=0):S(S), E(E){ a = S.y - E.y; b = E.x - S.x; c = E.x*S.y - S.x*E.y; } int Inter(const segment &tmp)const{ int t1 = Sign((S-E)^(tmp.S-E)); int t2 = Sign((S-E)^(tmp.E-E)); if(t1 == 0 && t2 == 0) return -1; if(t1*t2 == -1) return 1; if(abs(t1+t2) == 1)///如果完全相交或者有一点相交,不考虑重合 return 2; return false; } point crossNode(const segment &tmp)const {///两条线段的交点 point result; result.x = (c*tmp.b-tmp.c*b) / (a*tmp.b-tmp.a*b); result.y = (c*tmp.a-tmp.c*a) / (b*tmp.a-tmp.b*a); return result; } bool OnSeg(const point &p) {///判断点是否在线段上 if(Sign((S-E)^(p-E)) == 0) if(Sign((p.x-S.x)*(p.x-E.x)) <= 0) if(Sign((p.y-S.y)*(p.y-E.y)) <= 0) return true; return false; } }; struct Polygon { int N;///有N个点 point vertex[MAXN]; int Point_In_Poly(const point &p) {///点在多边形里面1,还是外面-1,还是边上 0 segment ray(p, point(FarX, p.y)); int cnt = 0; for(int i=0; i<N; i++) { segment L(vertex[i], vertex[i+1]); if(L.OnSeg(p)) return 0; if(ray.OnSeg(L.S)) { if(L.E.y-L.S.y > EPS) cnt ++; } else if(ray.OnSeg(L.E)) { if(L.S.y-L.E.y > EPS) cnt ++; } else if(L.Inter(ray)==1 && ray.Inter(L)==1) cnt++; } if(cnt % 2) return 1; return -1; } double Seg_In_Poly(const segment &L1) {///线段与多边形相交的长度,先求出线段与多边形有几个交点 point p[10]; int k=0; for(int i=0; i<N; i++) { segment L2(vertex[i], vertex[i+1]); if(L1.Inter(L2) == -1 && L2.Inter(L1) == -1) return 0; if(k<2 && L1.Inter(L2) && L2.Inter(L1)) { point t = L1.crossNode(L2); if(!k || !(p[0] == t) ) p[k++] = t; } } double len=0; if(k == 2) {///有两个不同的交点 len = Dist(p[0], p[1]); } else if(k == 1) {///有一个交点,判断哪个端点在多边形内 if(Point_In_Poly(L1.S) == 1) len = Dist(p[0], L1.S); else if(Point_In_Poly(L1.E) == 1) len = Dist(p[0], L1.E); } else if(Point_In_Poly(L1.S) == 1) {///没有交点的时候,判断线段是否在多边形内 len = Dist(L1.S, L1.E); } return len; } }; Polygon poly; bool cmp(point t1, point t2) { return Sign((t2-poly.vertex[0])^(t1-poly.vertex[0])) < 0; } int main() { int i, M, ki=0; scanf("%d", &poly.N); for(i=0; i<poly.N; i++) { scanf("%lf%lf", &poly.vertex[i].x, &poly.vertex[i].y); if(poly.vertex[ki].y > poly.vertex[i].y || (poly.vertex[ki].y == poly.vertex[i].y && poly.vertex[ki].x > poly.vertex[i].x) ) ki = i; } swap(poly.vertex[0], poly.vertex[ki]); sort(poly.vertex+1, poly.vertex+poly.N, cmp); poly.vertex[poly.N] = poly.vertex[0]; scanf("%d", &M); while(M--) { point A, B; scanf("%lf%lf%lf%lf", &A.x, &A.y, &B.x, &B.y); segment L(A, B); printf("%.6f ",poly.Seg_In_Poly(L)); } return 0; } /** 6 1 2 2 1 2 3 3 1 3 3 4 2 200 1 1 4 10 **/