题意:
一块有n个点的凸多边形面包要沾牛奶,每次可以沾的深度是h, 总共可以沾 k 次, 求最大沾取牛奶的面积。
题解:
枚举k条边,然后半平面交找最小剩余面积。。
又查不出错了,不想对拍了,这几天写计算几何都恶心死了,各种数据弱,模板写错了都不知道,下次用被卡的时候死活检查不出来了。。
改了好几回模板了,现在应该是对的,不知道我那里没考虑到,wa啊。。。
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 }