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

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4785

题意:一个房间(矩形),里面有一些家具(凸多边形),你有一个扫地机器(凸多边形),扫地机器可以扫地是它的第一个点,能扫地条件是机器完全在房间里面并且和家具没有交(机器可以穿过家具,但穿过的时候不能扫地),问扫地机器扫到的最大面积。

题解:在房间内的限制等同于机器移动的限制是在一个矩形内,然后不交多边形的限制就变成了 家具 和 机器求一个闵可夫斯基和 , 机器移动不能移动到这个闵可夫斯基和里面,所以问题转换成一个矩形里面有若干个凸多边形,问矩形内多边形没有覆盖到的面积。

这里由于n只有20 , 我们可以考虑直接暴力扫描线。我们把多边形的顶点以及交点求出来,然后平行于y轴的扫面线一直扫过去,相邻的扫描线是一个区间片,多边形要么是不在区间片里面,要么是横穿了这个区间片,交的结果是一个梯形,注意到,多个多边形的交的梯形不会相交,因为假如相交了,那么交点肯定在区间片中间,那么区间片就应该缩小(因为是扫关键点),

由于刚刚的结论,所以我们直接用梯形面积公式求出区间片的面积,累加即可。

注意:对于一个多边形,我一个区间片统计其贡献的时候,当且仅当该多边形贯穿区间片,不然会出现问题,自己脑部一下就知道了。

  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编辑  收藏