每个猪的位置不同,所以不能简单的表示出状态,all[i]表示第i个抛物线打掉了哪些猪,其值本身存储状态(二进制),只需要找所有有用的抛物线,然后状压f[i]表示i状态下最少用掉的鸟,转移方程见代码。
其中的m可以用来优化。代码虽然长,但是比较好懂。
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
int judge(double x,double y)
{
if(x>y) swap(x,y);
if(y-x>1e-6) return 1;
else return 0;
}
int t,f[1<<18];
struct doit{
double x,y;
}a[19];
struct node{
double data;int mark,tot;
}b[19];int all[19];
double cmp(doit a,doit b)
{
if(a.x==b.x)
return a.y<b.y;
else return a.x<b.x;
}
int cmp2(node a,node b)
{
return a.data<b.data;
}
int main()
{
cin>>t;
for(int i=1;i<=t;++i)
{
memset(f,0,sizeof(f));
int n,p;
cin>>n>>p;int u=1000;
if(p==1)
{
u=n/3+1;
if(n%3!=0) u++;
}
if(p==2)
{
u=n-n/3+1;
}
for(int i=1;i<=n;++i)
cin>>a[i-1].x>>a[i-1].y;
sort(a,a+n,cmp);
f[0]=0;int tot;
for(int i=tot=0;i<n;++i)
{
for(int j=i+1;j<n;++j)
{
if(a[i].x==a[j].x) continue;
double aa=(((a[i].y)/(a[i].x))-(a[j].y/a[j].x))/(a[i].x-a[j].x);
double bb=((a[i].y)/(a[i].x)-(aa*a[i].x));
if(aa>=0) continue;all[tot]=0;
all[tot]|=1<<i;all[tot]|=1<<j;
for(int k=j+1;k<n;++k)
{
double y1=a[k].x*a[k].x*aa+a[k].x*bb;
if(judge(y1,a[k].y)) continue;
all[tot]|=1<<k;
}tot++;
}
}
for(int i=0;i<n;++i)
all[tot++]=1<<i;
sort(all,all+tot);
tot=unique(all,all+tot)-all;
for(int j=0;j<(1<<n);++j)
f[j]=99999;
f[0]=0;
for(int j=0;j<(1<<n);++j)
for(int i=0;i<tot;++i)
{
f[j|all[i]]=min(f[j|all[i]],f[j]+1);
}
cout<<f[(1<<n)-1]<<endl;
}
}