题意:给你一个凸多边形的面包,然后告诉你牛奶的高度,和可以进行最多k次蘸牛奶,求面包最多能蘸到牛奶的面积
思路:dfs枚举边,然后向内推进h,用半平面交求不能蘸到牛奶的面积,用总面积减去面积,维护最大值
有一个小trick:k有可能会比边大,需要判断一下;
不得不说不知道是uva的机器比poj好还是数据比poj少,uva上只跑了300ms,而poj接近600ms。。。。。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
#define inf 0x7ffffff
using namespace std;
const double eps=1e-8;
int n,k,h,top,bot,dq[1000000];
int ln;
double ans,area,marea;
struct P
{
double x,y;
P(){}
P(double x,double y):x(x),y(y){
}
P operator +(P p){
return P(x+p.x,y+p.y);
}
P operator -(P p){
return P(x-p.x,y-p.y);
}
P operator *(double d){
return P(x*d,y*d);
}
double det(P p){
return x*p.y-y*p.x;
}
};
P p[1000000],s[1000000];
struct Line
{
P a,b;
double angle;
};
Line l[1000000],l1[1000000],l2[1000000];
int dblcmp(double k)
{
if(fabs(k)<eps)
return 0;
return k>0?1:-1;
}
P in(Line a,Line b){
return a.a+(a.b-a.a)*((b.b-b.a).det(b.a-a.a)/(b.b-b.a).det(a.b-a.a));
}
bool judge(Line a,Line b,Line c){
P r=in(b,c);
return dblcmp((a.a-r).det(a.b-r))<0; //顺时针大于0,逆时针小于0;
}
bool cmp(Line a,Line b){
int d=dblcmp(a.angle-b.angle);
if(!d)
return dblcmp((b.a-a.a).det(b.b-a.a))>0;
return d<0;
}
double dis(P a,P b)
{
double c=(a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
return sqrt(c);
}
void getarea()
{
area=0;
for(int i=0;i<n;i++)
area+=(p[i].x*p[i+1].y-p[i].y*p[i+1].x);
area=fabs(area);
area/=2;
}
Line getmove(double r,Line l)
{
Line l1;
double x=l.a.x-l.b.x;//顺逆时针只需要交换a,b就可以了。。。顺时针b-a,逆时针a-b
double y=l.a.y-l.b.y;
double L=dis(l.a,l.b);
l1.a.x=(l.a.x+r*y/L);
l1.a.y=(l.a.y-r*x/L);
l1.b.x=(l.b.x+r*y/L);
l1.b.y=(l.b.y-r*x/L);
l1.angle=l.angle;
return l1;
}
void solve()
{
int i,j;
for(i=0,j=0;i<ln;i++)
{
l2[i]=l1[i];
if(dblcmp(l2[i].angle-l2[j].angle)>0)
l2[++j]=l2[i];
}
int len=j+1;
top=1;
bot=0;
dq[0]=0;
dq[1]=1;
for(i=2;i<len;i++)
{
while(top>bot && judge(l2[i],l2[dq[top]],l2[dq[top-1]])) top--;
while(top>bot && judge(l2[i],l2[dq[bot]],l2[dq[bot+1]])) bot++;
dq[++top]=i;
}
while(top>bot && judge(l2[dq[bot]],l2[dq[top]],l2[dq[top-1]])) top--;
while(top>bot && judge(l2[dq[top]],l2[dq[bot]],l2[dq[bot+1]])) bot++;
dq[++top]=dq[bot];
int pn=0;
for(pn=0,i=bot;i<top;i++,pn++)
{
s[pn]=in(l2[dq[i+1]],l2[dq[i]]);
}
s[pn]=s[0];
if(pn>=3)
{
marea=0;
for(int i=0;i<pn;i++)
{
marea+=(s[i].x*s[i+1].y-s[i].y*s[i+1].x);
}
marea=fabs(marea);
marea/=2.0;
ans=max(ans,area-marea);
}
else
{
ans=max(ans,area);
}
}
int vis[100000];
int kep[1000];
void dfs(int index,int num,double r)
{
if(num-k+index>ln)
return;
if(num==k)
{
solve();
return ;
}
for(int i=index;i<ln;i++)
{
if(!vis[i])
{
vis[i]=1;
l1[i]=getmove(r,l[i]);
dfs(i+1,num+1,r);
vis[i]=0;
l1[i]=l[i];
}
}
}
int main()
{
while(~scanf("%d%d%d",&n,&k,&h) && !(n==k && k==h && h==0))
{
memset(vis,0,sizeof(vis));
ln=0;
ans=0;
for(int i=0;i<n;i++)
scanf("%lf%lf",&p[i].x,&p[i].y);
p[n]=p[0];
for(int i=0;i<n;i++)
{
l[ln].a=p[i];
l[ln].b=p[i+1];
l[ln].angle=atan2(l[ln].a.y-l[ln].b.y,l[ln].b.x-l[ln].a.x);
l1[ln]=l[ln];
ln++;
}
if(k>ln)
k=ln;
sort(l,l+ln,cmp);
sort(l1,l1+ln,cmp);
getarea();
double r=(double)h;
dfs(0,0,r);
printf("%.2lf\n",ans);
}
return 0;
}