[USACO06NOV]玉米田Corn Fields
阿新 • • 發佈:2018-12-15
題目
思路
資料大小已經很明顯的提示,這題是狀壓DP啊!
讀入以後,我們用F[i]來表示第i行上的草地情況,這裡F數組裡的是二進位制數。MAXSTATE是2n,也就是這道題的最大狀態(n列都是1)。
然後我們在0~MAXSTATE-1這些狀態裡找到合法狀態,也就是不能兩頭牛的草地是相鄰的。判斷方法就是把這個二進位制數左移一位and,然後右移一位and。如果這個狀態是合法的,那麼都應該返回0。
然後就開始動規,從第一行開始,在每行裡找所有狀態,如果這個狀態是合法的,且不會在貧瘠的草地上(和(j & F[i]) == j說明沒有草地種在貧瘠的地方),那麼接下來開始找上一行的合法情況(上下兩行之間沒有相鄰的草地),把上一行的情況數加到f[i][j]裡。
最後把最下面一行的每一列的情況書統統加起來,就是答案啦~
程式碼
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int n,w; int a[20],f[1<<18],g[1<<18]; int main() { scanf("%d%d",&n,&w); for(int i=1; i<=n; i++) scanf("%d",&a[i]); memset(f,63,sizeof(f)); f[0]=1; g[0]=w; for(int i=0; i<(1<<n); i++) { for(int j=1; j<=n; j++) { if(i&(1<<(j-1))) continue; if(g[i]>=a[j] && f[i|(1<<(j-1))]>=f[i]) { f[i|(1<<(j-1))]=f[i]; g[i|(1<<(j-1))]=max(g[i|(1<<(j-1))],g[i]-a[j]); } else if(g[i]<a[j] && f[i|(1<<(j-1))]>=f[i]+1) { f[i|(1<<(j-1))]=f[i]+1; g[i|(1<<(j-1))]=max(g[i|(1<<(j-1))],w-a[j]); } } } printf("%d",f[(1<<n)-1]); return 0; }