些许的计算几何+状压DP,(爆搜也能过!!!)
dp[s]为s为已经死了的猪的状态
#include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; #define ll long long #define re register #define fi first #define se second const double eps=1e-8; void read(int &a) { a=0; int d=1; char ch; while(ch=getchar(),ch>'9'||ch<'0') if(ch=='-') d=-1; a=ch^48; while(ch=getchar(),ch>='0'&&ch<='9') a=(a<<3)+(a<<1)+(ch^48); a*=d; } int f[1<<20],sta[1<<20],line[20][20]; pair <double,double> a[20]; inline void init() { for(re int i=0;i<(1<<18);i++) { re int j=1; for(;i&(1<<(j-1))&&j<=18;j++); sta[i]=j; } } void solve(double &x,double &y,double a1,double b1,double c1,double a2,double b2,double c2) { y=(a1*c2-a2*c1)/(a1*b2-a2*b1); x=(c1-b1*y)/a1; } int main() { init(); int T; read(T); while(T--) { memset(f,0x3f,sizeof(f)); memset(line,0,sizeof(line)); f[0]=0; int n,m; read(n); read(m); for(re int i=1;i<=n;i++) scanf("%lf %lf",&a[i].fi,&a[i].se); for(re int i=1;i<=n;i++) for(re int j=1;j<=n;j++) { if(fabs(a[i].fi-a[j].fi)<eps) continue; double d,b; solve(d,b,a[i].fi*a[i].fi,a[i].fi,a[i].se,a[j].fi*a[j].fi,a[j].fi,a[j].se); if(d>=0) continue; for(re int k=1;k<=n;k++) { if(fabs(d*a[k].fi*a[k].fi+b*a[k].fi-a[k].se)<eps) line[i][j]|=(1<<(k-1)); } } for(re int i=0;i<(1<<n);i++) { re int j=sta[i]; f[i|(1<<(j-1))]=min(f[i|(1<<(j-1))],f[i]+1); for(re int k=1;k<=n;k++) f[i|line[j][k]]=min(f[i|line[j][k]],f[i]+1); } printf("%d ",f[(1<<n)-1]); } return 0; }