洛谷P2831 [NOIP2016 提高組] 憤怒的小鳥——狀壓dp、預處理
阿新 • • 發佈:2021-10-16
題目連結
題目:憤怒的小鳥
思路過程
資料範圍非常小,\(n\leq 18\),可以考慮指數級時間複雜度的演算法。
借鑑曼哈頓路徑的狀壓dp演算法,可以設計出狀態:\(f(i)\)表示狀態為\(i\)時用鳥最小數。
狀態轉移很好想,預處理一下可以做到\(O(n^2)\)轉移
時間複雜度\(O(2^n n^2)\)
完整程式碼
浮生若夢,為歡幾何#include <bits/stdc++.h> using namespace std; const int N=18,INF=0x3f3f3f3f; const double eps=1e-8; int T,n,m; double x[N],y[N]; int f[1<<N],p[N][N]; double xx,yy; void calc(int i,int j) { double a,b,c,d,e,f; a=x[i]*x[i],b=x[i],c=y[i]; d=x[j]*x[j],e=x[j],f=y[j]; xx=(e*c-f*b)/(a*e-d*b); yy=(d*c-f*a)/(d*b-e*a); } int main() { scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); for(int i=0;i<n;i++) scanf("%lf%lf",&x[i],&y[i]); memset(p,0,sizeof(p)); for(int i=0;i<n;i++) for(int j=i+1;j<n;j++) { calc(i,j); if(xx>=0) continue; for(int k=0;k<n;k++) if(abs(y[k]-xx*x[k]*x[k]-yy*x[k])<eps) p[i][j]|=(1<<k); } memset(f,0x3f,sizeof(f)); f[0]=0; int bound=(1<<n)-1; for(int i=0;i<=bound;i++) { if(f[i]==INF) continue; for(int j=0;j<n;j++) { if(i>>j&1) continue; f[i|(1<<j)]=min(f[i|(1<<j)],f[i]+1); for(int k=j+1;k<n;k++) { if(i>>k&1 or !p[j][k]) continue; int nxt=i|p[j][k]; f[nxt]=min(f[nxt],f[i]+1); } } } int ans=f[bound]; for(int i=0;i<n;i++) ans=min(ans,f[bound^(1<<i)]+1); printf("%d\n",ans); } return 0; }