题目大意
解题思路
由于点的个数很少可以状态压缩,我们可以找到第一个没有覆盖的点,再随便枚举一个点(记得打break),两个点就可以确定一条抛物线,再扫一遍就可以知道有哪些点被覆盖,这个复杂度可以接受。
code
using namespace std;
int const maxn=18 ;
int t,n,m ,ans,f[(1 <<18 )+10 ],two[20 +10 ],inf=1 e9;
LD x [maxn+10 ],y [maxn+10 ];
int main(){
freopen("angrybirds.in" ,"r" ,stdin);
freopen("angrybirds.out" ,"w" ,stdout);
scanf("%d " ,&t);
two[0 ]=1 ;fo(i,1 ,20 )two[i]=two[i-1 ]*2 ;
fo(cas,1 ,t){
scanf("%d %d " ,&n,&m );
fo(i,1 ,n)scanf("%lf %lf " ,&x [i],&y [i]);
int maxs=(1 <<n)-1 ,nexts;LD a,b;
fo(i,1 ,maxs)f[i]=n;
fo(i,0 ,maxs-1 ){
fo(j,1 ,n)
if ((i&two[j-1 ])==0 ){
nexts=i+two[j-1 ];
f[nexts]=min(f[nexts],f[i]+1 );
fo(k,1 ,n)if (k!=j){
nexts=i+two[j-1 ]+(((i&two[k-1 ])==0 )?two[k-1 ]:0 );
a=(x [k]*y [j]-x [j]*y [k])/(x [j]*x [k]*( x [j]-x [k]));
if (a>=0 )continue ;
b=(y [j]-a*x [j]*x [j])/x [j];
fo(kk,1 ,n)
if (((nexts&two[kk-1 ])==0 )&&(a*x [kk]*x [kk]+b*x [kk]+1 e-12 >y [kk])
&&(a*x [kk]*x [kk]+b*x [kk]<1 e-12 +y [kk]))nexts+=two[kk-1 ];
f[nexts]=min(f[nexts],f[i]+1 );
}
break ;
}
}
printf ("%d \n" ,f[maxs]);
}
return 0 ;
}