POJ 1274 半平面交

题意:

一块有n个点的凸多边形面包要沾牛奶,每次可以沾的深度是h, 总共可以沾 k 次, 求最大沾取牛奶的面积。

 

题解:

枚举k条边,然后半平面交找最小剩余面积。。

又查不出错了,不想对拍了,这几天写计算几何都恶心死了,各种数据弱,模板写错了都不知道,下次用被卡的时候死活检查不出来了。。

改了好几回模板了,现在应该是对的,不知道我那里没考虑到,wa啊。。。

 

 

View Code
  1 #include <iostream>
  2 #include <cstring>
  3 #include <cstdlib>
  4 #include <cstdio>
  5 #include <algorithm>
  6 #include <cmath>
  7 
  8 #define N 222
  9 #define EPS 1e-7
 10 #define PI 3.14159265358979323
 11 #define INF 1e10
 12 
 13 using namespace std;
 14 
 15 struct PO
 16 {
 17     double x,y;
 18     void in(double x1,double y1)
 19     {
 20         x=x1,y=y1;
 21     }
 22     void prt() {printf("%lf     %lf\n",x,y);}
 23 }p[N],tp[N],f[N],s[N],o;
 24 
 25 struct LI
 26 {
 27     PO a,b;
 28     void prt() {printf("%lf    %lf    %lf     %lf\n",a.x,a.y,b.x,b.y);}
 29 }li[N],sl[N];
 30 
 31 int n,k,num;
 32 bool fg[N];
 33 double smin=INF,h;
 34 
 35 inline PO operator -(PO a,PO b)
 36 {
 37     PO c;
 38     c.x=a.x-b.x; c.y=a.y-b.y;
 39     return c;
 40 }
 41 
 42 inline int dc(double x)
 43 {
 44     if(x>EPS) return 1;
 45     else if(x<-EPS) return -1;
 46     return 0;
 47 }
 48 
 49 inline double cross(PO &a,PO &b,PO &c)
 50 {
 51     return (b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x);
 52 }
 53 
 54 inline double getlen(PO &a)
 55 {
 56     return sqrt(a.x*a.x+a.y*a.y);
 57 }
 58 
 59 inline PO rotate(PO a,double sss,double ccc)
 60 {
 61     PO ans;
 62     ans.x=a.x*ccc-a.y*sss;
 63     ans.y=a.x*sss+a.y*ccc;
 64     return ans;
 65 }
 66 
 67 inline PO getf(PO &a,PO &b)
 68 {
 69     PO ans; ans=b-a;
 70     ans=rotate(ans,sin(0.5*PI),cos(0.5*PI));
 71     double kk=getlen(ans);
 72     ans.x/=kk; ans.y/=kk;
 73     return ans;
 74 }
 75 
 76 inline PO getpoint(PO &a,PO &b,PO &c,PO &d)
 77 {
 78     PO ans,tp=b-a;
 79     double k1=cross(a,d,c);
 80     double k2=cross(b,c,d);
 81     ans.x=a.x+tp.x*k1/(k1+k2);
 82     ans.y=a.y+tp.y*k1/(k1+k2);
 83     return ans;
 84 }
 85 
 86 inline double getarea(PO *a,int g)
 87 {
 88     double ans=0.0;
 89     a[g+1]=a[1];
 90     for(int i=1;i<=g;i++) ans+=cross(o,a[i],a[i+1]);
 91     return ans;
 92 }
 93 
 94 inline void change(PO *a,int g)
 95 {
 96     for(int i=1;i<=(g>>1);g++) swap(a[i],a[g-i+1]);
 97 }
 98 
 99 inline void read()
100 {
101     memset(fg,0,sizeof fg);
102     for(int i=1;i<=n;i++) scanf("%lf%lf",&p[i].x,&p[i].y);
103     if(dc(getarea(p,n))<=0) change(p,n);
104     for(int i=1;i<n;i++)
105     {
106         li[i].a=p[i];
107         li[i].b=p[i+1];
108     }
109     li[n].a=p[n]; li[n].b=p[1];
110     for(int i=1;i<=n;i++) f[i]=getf(li[i].a,li[i].b);
111 }
112 
113 inline void getcut()
114 {
115     tp[1].in(-INF,-INF); tp[2].in(INF,-INF);
116     tp[3].in(INF,INF); tp[4].in(-INF,INF); tp[5]=tp[1];
117     int cp=4,tc;
118     for(int i=1;i<=n;i++)
119     {
120         tc=0;
121         for(int j=1;j<=cp;j++)
122         {
123             if(dc(cross(sl[i].a,sl[i].b,tp[j]))>=0) s[++tc]=tp[j];
124             if(dc(cross(sl[i].a,sl[i].b,tp[j])*cross(sl[i].a,sl[i].b,tp[j+1]))<0)
125                 s[++tc]=getpoint(sl[i].a,sl[i].b,tp[j],tp[j+1]);
126         }
127         s[tc+1]=s[1];
128         for(int j=1;j<=tc+1;j++) tp[j]=s[j];
129         cp=tc;
130     }
131     num=cp;
132 }
133 
134 inline void calc()
135 {
136     for(int i=1;i<=n;i++)
137     {
138         sl[i]=li[i];
139         if(!fg[i]) continue;
140         sl[i].a.x=sl[i].a.x+h*f[i].x;
141         sl[i].a.y=sl[i].a.y+h*f[i].y;
142         sl[i].b.x=sl[i].b.x+h*f[i].x;
143         sl[i].b.y=sl[i].b.y+h*f[i].y;
144     }
145     getcut();
146     if(!num) smin=0.0;
147     else smin=min(smin,fabs(getarea(s,num))*0.5);
148     //printf("%lf\n",smin);for(int i=1;i<=num;i++) s[i].prt();puts("\n");
149 }
150 
151 inline void dfs(int x,int nu)
152 {
153     if(dc(smin)==0) return;
154     if(n-x+1<k-nu) return;
155     if(nu==k) {calc();return;}
156     if(x>n) return;
157     fg[x]=1; dfs(x+1,nu+1);
158     fg[x]=0; dfs(x+1,nu);
159 }
160 
161 inline void go()
162 {
163     double sum=fabs(getarea(p,n))*0.5;
164     dfs(1,0);
165     //cout<<sum<<endl<<smin<<endl;
166     printf("%.2lf\n",sum-smin);
167 }
168 
169 int main()
170 {
171     while(scanf("%d%d%lf",&n,&k,&h))
172     {
173         if(n==0&&k==0&&dc(h)==0) break;
174         k=min(k,n);
175         if(dc(h)==0||k==0) puts("0.00");
176         else read(),go();
177     }
178     return 0;
179 }

 

 

posted @ 2013-02-27 22:12  proverbs  阅读(190)  评论(0编辑  收藏  举报