集合式状压dp
题意:
给定多个点,问至少有多少条开口向下的抛物线能将这些点完全覆盖
思路:
预处理出 $ n^2 $ 条抛物线,将该抛物线能覆盖到的点用状压表示,然后状态转移
cpp
int f[M];
int path[N][N],n,m;
double X[N],Y[N];
int cmp(double x,double y){
if(fabs(x-y)<eps)return 0;
if(x>y)return 1;
return -1;
}
void solve(){
cin>>n>>m;
for(int i=0;i<n;i++)cin>>X[i]>>Y[i];
memset(path,0,sizeof path);
for(int i=0;i<n;i++){
path[i][i]=1<<i;
for(int j=0;j<n;j++){
if(!cmp(X[i],X[j]))continue;
double a=(Y[i]/X[i]-Y[j]/X[j])/(X[i]-X[j]);
double b=Y[i]/X[i]-a*X[i];
if(a>0)continue;
int state=0;
for(int k=0;k<n;k++){
double x=X[k],y=Y[k];
if(!cmp(a*x*x+b*x,y))state+=1<<k;
}
path[i][j]=state;
}
}
memset(f,0x3f,sizeof f);
f[0]=0;
for(int i=0;i+1<1<<n;i++){
int x=0;
for(int j=0;j<n;j++){
if(!(i>>j&1)){
x=j;
break;
}
}
for(int j=0;j<n;j++){
f[i|path[x][j]]=min(f[i|path[x][j]],f[i]+1);
}
}
cout<<f[(1<<n)-1]<<"\n";
}