HDU.1693.Eat the Trees(插頭DP)
阿新 • • 發佈:2019-01-03
http://www.cnblogs.com/LadyLex/p/7326874.html
插頭DP。對於本題我們只需要記錄之前\(m\)個格子的\(m+1\)個插頭是否存在。
轉移時根據左邊、上邊是否有插頭討論。用位運算可以寫的很方便。
因為想對DP陣列壓壓維,我也覺得寫的好不直觀=-=。反正就是從上一個格子轉移,解決完一行將狀態左移一位轉給下一行。可以看上面連結裡的程式碼。
最簡單的插頭DP...反正我也是做過插頭DP的人了233
//0MS 1260K #include <cstdio> #include <cctype> #include <cstring> #include <algorithm> #define gc() getchar() typedef long long LL; const int N=12; LL f[2][(1<<N)+2];//m+1 bool mp[N][N]; inline int read() { int now=0;register char c=gc(); for(;!isdigit(c);c=gc()); for(;isdigit(c);now=now*10+c-'0',c=gc()); return now; } inline void Work(int x,int y,int lim,LL *f,LL *g) { if(mp[x][y]) for(int s=0,p1=1<<y-1,p2=1<<y; s<lim; ++s) { f[s^p1^p2]+=g[s]; if((s>>y-1&1)!=(s>>y&1)) f[s]+=g[s]; } else for(int s=0,p1=1<<y-1,p2=1<<y; s<lim; ++s) if(!(s&p1) && !(s&p2)) f[s]=g[s]; else f[s]=0; } int main() { for(int T=1,T2=read(); T<=T2; ++T) { int n=read(),m=read(),l1=1<<m,l2=1<<m+1; for(int i=1; i<=n; ++i) for(int j=1; j<=m; ++j) mp[i][j]=read(); int p=0; memset(f[p],0,sizeof f[p]); f[p][0]=1; for(int i=1; i<=n; ++i) { for(int j=1; j<=m; ++j) { p^=1, memset(f[p],0,sizeof f[p]); Work(i,j,l2,f[p],f[p^1]); } if(i!=n) { p^=1, memset(f[p],0,sizeof f[p]); for(int s=0; s<l1; ++s) f[p][s<<1]=f[p^1][s]; } } printf("Case %d: There are %lld ways to eat the trees.\n",T,f[p][0]);//f[n][m][0] } return 0; }