某谷链接
题意:选最少的抛物线来覆盖所有点。
注意到a<0,所以我们可以枚举两个点来构成一条抛物线,让后记这两个点构成的抛物线为 cov[i][j]cov[i][j]cov[i][j],让后他存的是这个抛物线能覆盖到的点的集合,把它存成一个二进制。当然可能存在点与其他任何点都够不成抛物线,这样的点特殊记录下就好啦。两个点连线与x轴垂直的时候这两个点也不能构成抛物线,特判一下即可。
现在我们预处理出来了covcovcov数组,转移方程为f[i∣cov[x][j]]=min(f[i∣cov[x][j]],f[i]+1)f[i|cov[x][j]]=min(f[i|cov[x][j]],f[i]+1)f[i∣cov[x][j]]=min(f[i∣cov[x][j]],f[i]+1)
从小到大依次枚举状态i即可。
//#pragma GCC optimize(2)
#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<map>
#include<cmath>
#include<cctype>
#include<vector>
#include<set>
#include<queue>
#include<algorithm>
#include<sstream>
#include<ctime>
#include<cstdlib>
#define X first
#define Y second
#define L (u<<1)
#define R (u<<1|1)
#define pb push_back
#define mk make_pair
#define Mid (tr[u].l+tr[u].r>>1)
#define Len(u) (tr[u].r-tr[u].l+1)
#define random(a,b) ((a)+rand()%((b)-(a)+1))
#define db puts("---")
using namespace std;//void rd_cre() { freopen("d://dp//data.txt","w",stdout); srand(time(NULL)); }
//void rd_ac() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//AC.txt","w",stdout); }
//void rd_wa() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//WA.txt","w",stdout); }typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> PII;const int N=21,M=1<<N,mod=1e9+7,INF=0x3f3f3f3f;
const double eps=1e-6;int n,m;
int f[M],cov[N][N];
struct Node
{double x,y;
}p[N];int sgn(double x)
{if(abs(x)<eps) return 0;if(x<0) return -1;else return 1;
}int main()
{
// ios::sync_with_stdio(false);
// cin.tie(0);int _; scanf("%d",&_);while(_--){scanf("%d%d",&n,&m);for(int i=1;i<=n;i++) scanf("%lf%lf",&p[i].x,&p[i].y);memset(cov,0,sizeof(cov));for(int i=1;i<=n;i++){cov[i][i]=1<<(i-1);for(int j=1;j<=n;j++){double x1=p[i].x,y1=p[i].y;double x2=p[j].x,y2=p[j].y;if(!sgn(x1-x2)) continue;double a=(y1/x1-y2/x2)/(x1-x2);double b=y1/x1-a*x1;if(sgn(a)>=0) continue;for(int k=1;k<=n;k++){double x=p[k].x,y=p[k].y;if(!sgn(a*x*x+b*x-y)) cov[i][j]+=(1<<(k-1));}}}memset(f,0x3f,sizeof(f));f[0]=0;for(int i=0;i+1<1<<n;i++){int id=0;for(int j=1;j<=n;j++) if(!(i>>(j-1)&1)) { id=j; break; }for(int j=1;j<=n;j++) f[i|cov[id][j]]=min(f[i|cov[id][j]],f[i]+1);}printf("%d\n",f[(1<<n)-1]);}return 0;
}
/**/