【GDOI2004】【可怜的绵羊】

来源:互联网 发布:淘宝中差评多久消失 编辑:程序博客网 时间:2024/04/28 04:20

题目大意

给出一个凸包,让你求一个不包含一些点的新凸包,用原来凸包上的点。

解题思路

新的凸包可以割成若干个三角形,三角形内部一定不包含那些点,所以外部的点一定等于总点数。我们可以求出一条线一边所含点的个数,可是这有交集。考虑到新凸包上的点是原凸包的子集,交集一定在原凸包外。我们就可以n^2预处理出那些点在凸包内,n^3处理处一条线一边的点数,再n^3DP。判断点可以使用叉积,求出相对方向即可判断是否在凸包内和在一条线的哪边,枚举起点,f[i]表示到i的最优答案,枚举j下一个选谁,转移即可。

code

#include<set>#include<cmath>#include<cstdio>#include<cstring>#include<algorithm>#define LL long long#define fo(i,j,k) for(int i=j;i<=k;i++)#define fd(i,j,k) for(int i=j;i>=k;i--)using namespace std;int const maxn=100,maxm=400;LL n,m,x[maxn+10],y[maxn+10],p[maxm+10],q[maxm+10],cnt[maxn+10][maxn+10],cntt[maxn+10][maxn+10];bool in[maxm+10];LL f[maxn+10];LL count(LL x,LL y,LL xx,LL yy){    return x*yy-y*xx;}int main(){    freopen("d.in","r",stdin);    freopen("d.out","w",stdout);    scanf("%lld",&n);    fo(i,1,n)        scanf("%lld%lld",&x[i],&y[i]);    scanf("%lld",&m);    fo(i,1,m)        scanf("%lld%lld",&p[i],&q[i]);    LL pon=0;    fo(i,1,m){        in[i]=1;        fo(j,1,n)            if(count(x[j%n+1]-x[j],y[j%n+1]-y[j],p[i]-x[j],q[i]-y[j])<0){                in[i]=0;                break;            }        pon+=in[i];    }    fo(i,1,n)        fo(j,1,n)            if(i!=j)                fo(k,1,m)                    if(in[k])                        cnt[i][j]+=(count(x[j]-x[i],y[j]-y[i],p[k]-x[i],q[k]-y[i])<=0);    LL ans=0;    fo(i,1,n-2){        memset(f,0,sizeof(f));        fo(j,i+1,n-1)            fo(k,j+1,n)                if(cnt[i][j]+cnt[j][k]+cnt[k][i]==pon)                    f[k]=max(f[k],f[j]+abs(count(x[k]-x[i],y[k]-y[i],x[j]-x[i],y[j]-y[i])));        fo(j,i+2,n)ans=max(ans,f[j]);    }    if(ans==0)printf("die");    else printf("%.2lf",ans/2.0);    return 0;}
0 0
原创粉丝点击