bzoj 2618[Cqoi2006]凸多边形 - 半平面交
2618: [Cqoi2006]凸多边形
Time Limit: 5 Sec Memory Limit: 128 MBDescription
逆时针给出n个凸多边形的顶点坐标,求它们交的面积。例如n=2时,两个凸多边形如下图:
则相交部分的面积为5.233。
Input
第一行有一个整数n,表示凸多边形的个数,以下依次描述各个多边形。第i个多边形的第一行包含一个整数mi,表示多边形的边数,以下mi行每行两个整数,逆时针给出各个顶点的坐标。
Output
输出文件仅包含一个实数,表示相交部分的面积,保留三位小数。
Sample Input
2
6
-2 0
-1 -2
1 -2
2 0
1 2
-1 2
4
0 -3
1 -1
2 2
-1 0
6
-2 0
-1 -2
1 -2
2 0
1 2
-1 2
4
0 -3
1 -1
2 2
-1 0
Sample Output
5.233
HINT
100%的数据满足:2<=n<=10,3<=mi<=50,每维坐标为[-1000,1000]内的整数
一道练习半平面交的好题
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <algorithm> 6 #define LL long long 7 8 using namespace std; 9 10 const int MAXN = 10000; 11 const double eps = 1e-6; 12 int N, m; 13 int tot = 0; 14 int head, tail; 15 int s[MAXN]; 16 17 inline LL read() 18 { 19 LL x = 0, w = 1; char ch = 0; 20 while(ch < '0' || ch > '9') { 21 if(ch == '-') { 22 w = -1; 23 } 24 ch = getchar(); 25 } 26 while(ch >= '0' && ch <= '9') { 27 x = x * 10 + ch - '0'; 28 ch = getchar(); 29 } 30 return x * w; 31 } 32 33 struct Point { 34 double x, y; 35 } p[MAXN], n[MAXN]; 36 37 struct Line { 38 Point p, v; 39 double k; 40 } l[MAXN], tmp[MAXN]; 41 42 Point operator *(Point a, double k) 43 { 44 Point t; 45 t = a; 46 t.x *= k ,t.y *= k; 47 return t; 48 } 49 50 double operator ^(Point a, Point b) 51 { 52 return a.x * b.y - a.y * b.x; 53 } 54 55 Point operator +(Point a, Point b) 56 { 57 Point t; 58 t.x = a.x + b.x, t.y = a.y + b.y; 59 return t; 60 } 61 62 Point operator -(Point a, Point b) 63 { 64 Point t; 65 t.x = a.x - b.x, t.y = a.y - b.y; 66 return t; 67 } 68 69 Point inter(Line a, Line b) 70 { 71 Point t, u; 72 double S1, S2; 73 u = b.p - a.p; 74 S1 = u ^ a.v, S2 = a.v ^ b.v; 75 t = b.p + b.v * (S1 / S2); 76 return t; 77 } 78 79 int sign(double x) 80 { 81 double d = fabs(x); 82 if(d <= eps) { 83 return 0; 84 } else if(x > 0) { 85 return 1; 86 } else { 87 return -1; 88 } 89 } 90 91 bool judge(Point p, Line a) 92 { 93 //cout<<p.x<<" "<<p.y<<endl; 94 Point u = p - a.p, v = a.v; 95 // cout<<u.x<<" "<<u.y<<" "<<v.x<<" "<<v.y<<endl; 96 // cout<<(u ^ v)<<endl; 97 if(sign(u ^ v) >= 0) { 98 return true; 99 } 100 return false; 101 } 102 103 bool cmp(Line a, Line b) 104 { 105 if(a.k == b.k) { 106 if(judge(a.p, b)) { 107 return false; 108 } else { 109 return true; 110 } 111 } 112 return a.k < b.k; 113 } 114 115 void work() 116 { 117 head = 0, tail = 0; 118 for(int i = 1; i <= tot; i++) { 119 Point p = inter(l[s[head]], l[s[head + 1]]); 120 int x = s[head], y = s[head + 1]; 121 // cout<<s[head]<<" "<<s[head + 1]<<" "<<p.x<<" "<<p.y<<endl; 122 // cout<<l[x].p.x<<" "<<l[x].p.y<<" "<<l[x].v.x<<" "<<l[x].v.y<<endl; 123 // cout<<l[y].p.x<<" "<<l[y].p.y<<" "<<l[y].v.x<<" "<<l[y].v.y<<endl; 124 //cout<<p.x<<" "<<p.y<<endl; 125 while(tail > head + 1 && judge(inter(l[s[tail - 1]], l[s[tail - 2]]), l[i])) { 126 tail--; 127 } 128 while((head + 1 < tail) && judge(inter(l[s[head]], l[s[head + 1]]), l[i])) { 129 head++; 130 } 131 s[tail++] = i; 132 } 133 while(tail > head + 1 && judge(inter(l[s[tail - 1]], l[s[tail - 2]]), l[s[head]])) { 134 tail--; 135 } 136 /*while(tail > head + 1 && judge(inter(l[s[head]], l[s[head + 1]]), l[tail - 1])) { 137 head++; 138 } 139 /*for(int i = head; i < tail; i++) { 140 cout<<l[s[i]].k<<" "; 141 } 142 cout<<endl;*/ 143 double ans = 0; 144 int cnt = 0; 145 for(int i = head; i < tail - 1; i++) { 146 n[++cnt] = inter(l[s[i]], l[s[i + 1]]); 147 } 148 n[++cnt] = inter(l[s[tail - 1]], l[s[head]]); 149 if(cnt == 0 || cnt == 1) { 150 printf("0.000\n"); 151 return; 152 } 153 for(int i = 1; i <= cnt; i++) { 154 ans += n[i] ^ n[i % cnt + 1]; 155 } 156 // cout<<ans<<endl; 157 ans = ans / 2; 158 printf("%.3lf\n", ans); 159 } 160 161 int main() 162 { 163 N = read(); 164 for(int i = 1; i <= N; i++) { 165 m = read(); 166 for(int i = 1; i <= m; i++) { 167 p[i].x = read(), p[i].y = read(); 168 } 169 for(int i = 1; i <= m; i++) { 170 l[++tot].p = p[i]; 171 l[tot].v = p[i % m + 1] - p[i]; 172 l[tot].k = atan2(l[tot].v.y, l[tot].v.x); 173 // cout<<l[tot].k<<" "<<" "<<l[tot].p.x<<" "<<l[tot].p.y<<endl;; 174 } 175 //cout<<endl; 176 } 177 sort(l + 1, l + tot + 1, cmp); 178 int cnt = tot; 179 tot = 0; 180 for(int i = 1; i <= cnt; i++) { 181 if(l[i].k != l[i - 1].k || i == 1) { 182 tmp[++tot] = l[i]; 183 } 184 } 185 for(int i = 1; i <= tot; i++) { 186 l[i] = tmp[i]; 187 } 188 /*for(int i = 1; i <= tot; i++) { 189 cout<<l[i].k<<" "; 190 } 191 cout<<endl;*/ 192 work(); 193 }