愤怒的小鸟
题解:
去年noip的时候写的暴力然后就有80分
正解比较显然
先枚举状态i 表示存在哪些猪,再枚举转移(由两个点确定最大能消灭多少)
另外一个套路就是先确定一个点
于是复杂度就是T*n*2^n了
两个点在一条直线上和a>0都要舍去
代码还是挺好写的
代码:
#include <bits/stdc++.h> using namespace std; #define rint register int #define IL inline #define rep(i,h,t) for (rint i=h;i<=t;i++) #define dep(i,t,h) for (rint i=t;i>=h;i--) #define me(x) memset(x,0,sizeof(x)) const int N=(1<<20)+10; double eps=1e-8; double a[20],b[20]; int f[N],n,m,ans[20][20]; const int INF=1e9; IL int js(int x,int y) { double ve1[3],ve2[3]; ve1[1]=a[x],ve1[2]=a[y]; ve2[1]=b[x],ve2[2]=b[y]; double t=ve1[1]*ve1[2]-ve1[2]*ve1[2]; if (abs(t)<eps) return(0); double x1=(ve2[1]/ve1[1]*ve1[2]-ve2[2])/t; double x2=(ve2[1]-ve1[1]*ve1[1]*x1)/ve1[1]; if (x1>0) return(0); int ans=0; rep(i,1,n) { if (abs(x1*a[i]*a[i]+x2*a[i]-b[i])<eps) ans=ans|(1<<(i-1)); int cnt=1; cnt++; } return(ans); } int main() { freopen("1.in","r",stdin); freopen("1.out","w",stdout); ios::sync_with_stdio(false); int T; cin>>T; rep(kk,1,T) { cin>>n>>m; rep(i,1,n) cin>>a[i]>>b[i]; me(f); rep(i,1,n) { rep(j,1,n) if (i!=j) ans[i][j]=js(i,j); ans[i][i]=(1<<(i-1)); } rep(i,0,(1<<n)-1) f[i]=INF; f[0]=0; rep(i,0,(1<<n)-1) { if (f[i]!=INF) { int j; for (j=1;j<=n;j++) if (((i>>(j-1))&1)==0) break; rep(k,1,n) f[i|ans[j][k]]=min(f[i|ans[j][k]],f[i]+1); } } cout<<f[(1<<n)-1]<<endl; } return 0; }