# 【hdu4785】【闵可夫斯基和】 Exhausted Robot

  1 #include<bits/stdc++.h>
2 using namespace std;
3 #define eps 1e-8
4 const int N = 1e3+9;
5 const double inf = 1e6;
6 int sgn(double x){
7     if( fabs(x) < eps) return 0;
8     if( x < 0 ) return -1;
9     return 1;
10 }
11 struct Point{
12     double x,y;
13     Point operator - (const Point& b)const{
14         return (Point){x-b.x,y-b.y};
15     }
16     Point operator + (const Point& b)const{
17         return (Point){x+b.x,y+b.y};
18     }
19     bool operator < (const Point& b)const{
20         if( sgn(x - b.x) == 0 ) return y < b.y;
21         return x < b.x;
22     }
23 }va[N],vb[N],rec[10];
24 double cross(Point a,Point b){
25     return a.x * b.y - b.x * a.y;
26 }
27 vector<Point> a[N],b[N];
28 int n;
29 double xl,yl,xr,yr;
30 double X[N];
31 double mi[N],mx[N];
32 int cnt;
33 bool insert(Point a,Point b,Point c,Point d){
34     return
35         max(a.x,b.x) >= min(c.x,d.x) &&
36         max(c.x,d.x) >= min(a.x,b.x) &&
37         max(a.y,b.y) >= min(c.y,d.y) &&
38         max(c.y,d.y) >= min(a.y,b.y) &&
39         sgn(cross(c-a,b-a))*sgn(cross(d-a,b-a))<=0 &&
40         sgn(cross(a-c,d-c))*sgn(cross(b-c,d-c))<=0;
41 }
42 Point segcross(Point a,Point b,Point c,Point d){
43     double u = cross(b-a,c-a) , v = cross(a-b,d-b);
44     return (Point){ (c.x*v+d.x*u)/(u+v) , (c.y*v+d.y*u)/(u+v)};
45 }
46 vector<Point> Minke(vector<Point> pa,vector<Point> pb){
47     int na = pa.size(),nb = pb.size();
48     //
49     int ida = 0, idb = 0;
50     for(int i = 0;i<na;++i) if(pa[i] < pa[ida]) ida = i;
51     for(int i = 0;i<nb;++i) if(pb[i] < pb[idb]) idb = i;
52     vector<Point> ta , tb;
53     for(int i = 0;i<na;++i){
54         ta.push_back(pa[ida]);
55         ida = (ida+1)%na;
56     }
57     for(int i = 0;i<nb;++i){
58         tb.push_back(pb[idb]);
59         idb = (idb+1)%nb;
60     }
61     pa = ta; pb = tb;
62
63     for(int i = 0 ; i < na-1;++i) va[i] = pa[i+1] - pa[i];
64     va[na-1] = pa[0] - pa[na-1];
65     for(int i = 0 ; i < nb-1;++i) vb[i] = pb[i+1] - pb[i];
66     vb[nb-1] = pb[0] - pb[nb-1];
67     vector<Point> pc;
68     Point tem;
69     tem = pa[0] + pb[0];
70     pc.push_back(tem);
71     int p1 = 0, p2 = 0;
72     while(p1 < na && p2 < nb){
73         tem = tem + ( (cross(va[p1],vb[p2]) >= 0 ) ? va[p1++] : vb[p2++]);
74         pc.push_back(tem);
75     }
76     while(p1 < na){
77         tem = tem + va[p1++];
78         pc.push_back(tem);
79     }
80     while(p2 < nb){
81         tem = tem + vb[p2++];
82         pc.push_back(tem);
83     }
84     //
85     return pc;
86 }
87 void init(){
88     double xmi = a[n+1][0].x,ymi = a[n+1][0].y,xmx = xmi , ymx = ymi;
89     for(auto it : a[n+1]){
90         xmi = min(xmi,it.x) , xmx = max(xmx,it.x);
91         ymi = min(ymi,it.y) , ymx = max(ymx,it.y);
92     }
93     xl -= xmi; xr -= xmx;
94     yl -= ymi; yr -= ymx;
95
96     for(int i = 0;i<a[n+1].size();++i){
97         a[n+1][i].x = -a[n+1][i].x;
98         a[n+1][i].y = -a[n+1][i].y;
99     }
100     for(int i = 1;i<=n;++i){
101         b[i] = Minke(a[n+1],a[i]);
102     }
103     for(int i = 1;i<=n;++i){
104         mi[i] = b[i][0].x , mx[i] = mi[i];
105         for(auto it : b[i]){
106             mi[i] = min(mi[i],it.x);
107             mx[i] = max(mx[i],it.x);
108         }
109     }
110     X[++cnt] = xl;
111     X[++cnt] = xr;
112     for(int i = 1;i<=n;++i){
113         for(auto it : b[i]){
114             if(it.x < xl + eps || it.x > xr - eps ) continue;
115             X[++cnt] = it.x;
116         }
117     }
118     for(int i = 1;i<=n;++i){
119         for(int j = i+1;j<=n;++j){
120             for(int ii = 0;ii<b[i].size()-1;++ii){
121                 for(int jj = 0;jj<b[j].size()-1;++jj){
122                     Point s1 = b[i][ii] , e1 = b[i][ii+1];
123                     Point s2 = b[j][jj] , e2 = b[j][jj+1];
124                     if( sgn(cross(e1 - s1,s2 - s1) ) == 0 && sgn(cross(e1 - s1,e2 - s1) == 0 ) ) continue;
125                     if( insert(s1,e1,s2,e2) ){
126                         Point tem = segcross(s1,e1,s2,e2);
127                         if(tem.x < xl + eps || tem.x > xr - eps ) continue;
128                         X[++cnt] = tem.x;
129                     }
130                 }
131             }
132         }
133     }
134     rec[0] = (Point){xl,yl}; rec[1] = (Point){xr,yl};
135     rec[2] = (Point){xr,yr}; rec[3] = (Point){xl,yr}; rec[4] = rec[0];
136     for(int i = 1;i<=n;++i){
137         for(int j = 0;j<b[i].size()-1;++j){
138             for(int k = 0;k<4;++k){
139                 if(insert(b[i][j],b[i][j+1],rec[k],rec[k+1])){
140                     Point res = segcross(b[i][j],b[i][j+1],rec[k],rec[k+1]);
141                     X[++cnt] = res.x;
142                 }
143             }
144         }
145     }
146     sort(X+1,X+1+cnt);
147 }
148 void crosspol(vector<Point> p, double xx , vector< pair<double,int> >& Y){
149     Point le = (Point){xx,-inf} , ri = (Point){xx,inf};
150     vector<double> vec;
151     for(int j = 0;j<p.size()-1;++j){
152         if( sgn( p[j].x - le.x) == 0 && sgn(p[j+1].x - le.x) == 0){
153             vec.push_back(p[j].y);
154             vec.push_back(p[j+1].y);
155         }
156         else{
157             if(insert(le,ri,p[j],p[j+1]) ){
158                 Point tem = segcross(le,ri,p[j],p[j+1]);
159                 vec.push_back(tem.y);
160             }
161         }
162     }
163     sort(vec.begin(),vec.end());
164     if(vec.size() < 2) return;
165     double ya = vec[0] , yb = vec[vec.size()-1];
166     Y.push_back({max(ya,yl),1}); Y.push_back({min(yb,yr),-1});
167 }
168 double solve_len(vector< pair<double,int> > Y){
169     sort(Y.begin(),Y.end());
170     int num = 0;
171     double res = 0;
172     double las;
173     for(auto it : Y){
174         if(num==0 && it.second == 1){
175             las = it.first;
176             ++num;
177             continue;
178         }
179         num += it.second;
180         if(num == 0 && it.second == -1) res += (it.first - las);
181     }
182     return res;
183 }
184 void solve(){
185     double ans = 0;
186     for(int i = 1;i<cnt;++i){
187         vector< pair<double,int> > Yl,Yr;
188         for(int j = 1;j<=n;++j){
189             if(mx[j] < X[i] + eps || mi[j] > X[i+1] - eps ) continue;
190             crosspol(b[j],X[i],Yl);
191             crosspol(b[j],X[i+1],Yr);
192         }
193         double le = solve_len(Yl) , ri = solve_len(Yr);
194         ans += (ri + le) * (X[i+1] - X[i]) * 0.5;
195     }
196     printf("%.3f\n",(xr-xl)*(yr-yl) - ans);
197     return;
198 }
199 int main(){
200     int T; scanf("%d",&T);
201     for(int cas = 1;cas <= T;++cas){
202         cnt = 0;
203         printf("Case #%d: ",cas);
204         scanf("%d",&n);
205         for(int i = 1;i<=n+1;++i){
206             a[i].clear();
207             int m; scanf("%d",&m);
208             for(int j = 1;j<=m;++j){
209                 Point tem;
210                 scanf("%lf %lf",&tem.x,&tem.y);
211                 a[i].push_back(tem);
212             }
213         }
214         scanf("%lf %lf %lf %lf",&xl,&yl,&xr,&yr);
215         init();
216         solve();
217     }
218     return 0;
219 }
220 /*
221 6
222 1
223 3
224 0 0
225 10 0
226 10 10
227 4
228 0 0
229 1 0
230 1 1
231 0 1
232 0 0 10 10
233 */
View Code

posted @ 2020-04-16 14:31  小布鞋  阅读(140)  评论(0编辑  收藏