【題解】洛谷P2831[NOIP2016]憤怒的小鳥 狀壓DP
阿新 • • 發佈:2019-01-23
dp[i]表示i狀態時所需要的最少的小鳥數,state[i]表示第i條拋物線所打掉的小豬狀態,
dp[i|state[j]]=min(dp[i|state[j]],dp[i]+1)
#include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; #define eps 1e-6 int n,m; const int N=18; int dp[1<<N];//dp[i]表示i狀態時所需最少小鳥數 double x[N],y[N]; int state[510];//記錄每條拋物線 int cnt; int main() { //freopen("in.txt","r",stdin); int t; double a,b; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); cnt=0; memset(dp,0x3f,sizeof(dp)); dp[0]=0; for(int i=0;i<n;i++) scanf("%lf%lf",&x[i],&y[i]); for(int i=0;i<n;i++) { state[cnt++]=(1<<i); for(int j=i+1,k=0;j<n;j++) { if((k>>j)&1)continue; a=(y[j]*x[i]-y[i]*x[j])/(x[i]*x[j]*(x[j]-x[i])); b=(y[i]*x[j]*x[j]-y[j]*x[i]*x[i])/(x[i]*x[j]*(x[j]-x[i])); if(a>=-eps)continue; state[cnt]=(1<<i); for(int o=j;o<n;o++) if(fabs(a*x[o]*x[o]+b*x[o]-y[o])<=eps) { k|=(1<<o); state[cnt]|=(1<<o); } cnt++; } } for(int i=0;i<(1<<n);i++) for(int j=0;j<cnt;j++) dp[i|state[j]]=min(dp[i|state[j]],dp[i]+1); printf("%d\n",dp[(1<<n)-1]); } return 0; }