正解O(Tn22n)
- 把所有可能的抛物线都枚举出来,然后DP,保证这些抛物线不重复经过某个点。
- 注意精度!
#include<cstdio>
#include<cstring>
#define ri register int
#define min(a,b) a<b?a:b
#include<cmath>
using namespace std;
const double ep=1e-6;
double x[18],y[18];
int dp[1<<18],lines[200];
int T,n,m,s;
void pre(){
memset(dp,127,sizeof dp);
s=dp[0]=0;
for(ri i=0;i<n;++i)
{
lines[s++]=1<<i;
for(ri j=i+1,vis=0;j<n;++j)
if(vis&(1<<j)) continue;
else
{
double a=(x[j]*y[i]-x[i]*y[j])/(x[i]*x[j]*(x[i]-x[j]));
double b=(x[i]*x[i]*y[j]-x[j]*x[j]*y[i])/(x[i]*x[j]*(x[i]-x[j]));
if(a>=0) continue;
lines[s]=1<<i;
for(ri k=j;k<n;++k)
if(abs(a*x[k]*x[k]+b*x[k]-y[k])<ep)
vis|=1<<k,lines[s]|=1<<k;
s++;
}
}
}
void solve(){
for(ri i=0;i<1<<n;++i)
for(ri j=0;j<s;++j)
dp[i|lines[j]]=min(dp[i|lines[j]],dp[i]+1);
}
int main(){
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
for(ri i=0;i<n;++i) scanf("%lf%lf",&x[i],&y[i]);
pre();
solve();
printf("%d\n",dp[(1<<n)-1]);
}
return 0;
}