题目大意:
原题翻译细节有误,加上我自己看丢条件,导致我想了半天没想通。
题意是有n个白点,m个黑点,还有原点(0,0)无色,黑白点的纵坐标均大于0,且无三点共线,要求一个必须包含原点的凸包,使得凸包中白点的数量减黑点的最多。n+m小等于100。
解题思路:
如果没有“纵坐标均大于0”,“无三点共线“,“必须包含原点”三个条件,题目将变得很恶心,然而原题没翻译第三个条件,我看丢了前两个……
这样就好做了,直接 O(n3) O ( n 3 ) 三角剖分出每两个点与原点组成三角形内部点值,f[i][j]表示i点从j点转移来的最优值,dp下一个点时直接判该点是否是在直线ji左侧即可转移(就是满足凸包性质),dp复杂度也是 O(n3) O ( n 3 ) 。
不过这两步都可以有平衡树维护到 O(n2log2n) O ( n 2 l o g 2 n ) ,可以参考这里。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int getint()
{
int i=0,f=1;char c;
for(c=getchar();(c!='-')&&(c<'0'||c>'9');c=getchar());
if(c=='-')f=-1,c=getchar();
for(;c>='0'&&c<='9';c=getchar())i=(i<<3)+(i<<1)+c-'0';
return i*f;
}
const int N=105;
struct point
{
int x,y,t;
point(){}
point(int _x,int _y):x(_x),y(_y){}
inline friend point operator - (const point &a,const point &b)
{return point(a.x-b.x,a.y-b.y);}
inline friend ll operator * (const point &a,const point &b)
{return 1ll*a.x*b.y-1ll*a.y*b.x;}
inline friend bool operator < (const point &a,const point &b)
{return atan2(a.y,a.x)<atan2(b.y,b.x);}
}p[N];
int n,m,ans,g[N][N],f[N][N];
int main()
{
n=getint(),m=getint();
for(int i=1;i<=n;i++)p[i].x=getint(),p[i].y=getint(),p[i].t=1;
for(int i=n+1;i<=n+m;i++)p[i].x=getint(),p[i].y=getint(),p[i].t=-1;
n+=m;sort(p+1,p+n+1);
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
for(int k=i+1;k<j;k++)
if((p[i]-p[k])*(p[j]-p[k])>0)
g[i][j]+=p[k].t;
for(int i=1;i<=n;i++)
{
f[i][0]=p[i].t;
for(int j=1;j<i;j++)
for(int k=0;k<j;k++)
if((p[k]-p[i])*(p[j]-p[i])>=0)
f[i][j]=max(f[i][j],f[j][k]+g[j][i]+p[i].t);
}
for(int i=1;i<=n;i++)
for(int j=1;j<i;j++)
ans=max(ans,f[i][j]);
cout<<ans;
return 0;
}