P1879 [USACO06NOV]玉米田Corn Fields (狀壓dp入門)
阿新 • • 發佈:2018-12-16
題目連結: https://www.luogu.org/problemnew/show/P1879
具體思路: 我們可以先把所有合法的情況枚舉出來,然後對第一行判斷有多少種情況滿足,然後對於剩下的行數,我們可以繼續列舉,但是列舉的時候要注意,要判斷一下和它的上面一行的各種情況會不會衝突,然後一直列舉就可以了.
注意點:位運算子的優先順序比等號之類的低,所以如果要判斷的話,最好放在括號裡面判斷.
AC程式碼:
#include<bits/stdc++.h> using namespace std; # define ll long long const int maxn = 10000+100; # define inf 0x3f3f3f3f const int mod = 1e9; int Map[maxn]; int a[maxn][maxn]; int dp[maxn][maxn]; int ok[maxn]; int main() { int n,m; scanf("%d %d",&n,&m); for(int i=1; i<=n; i++) { for(int j=1; j<=m; j++) { scanf("%d",&a[i][j]); Map[i]=(Map[i]<<1)+a[i][j];//把初始的圖存起來 } } int maxstate=(1<<m)-1;//所有情況 for(int i=0; i<=maxstate; i++) { if((((i<<1)&i)==0)&(((i>>1)&i)==0))//如果當前這種情況符合,只有他的左邊和右邊都不會有相鄰的1 { ok[i]=1; } } for(int i=0; i<=maxstate; i++) { if((ok[i]==1)&(((i&Map[1])==i))) { dp[1][i]=1; } }//列舉第一行 for(int i=2; i<=n; i++) { for(int j=0; j<=maxstate; j++) { if(ok[j]&((j&Map[i])==j)) { for(int k=0; k<=maxstate; k++) { if(((j&k)==0)&ok[k]) dp[i][j]=(dp[i][j]+dp[i-1][k])%mod; } } } } ll sum=0; for(int i=0; i<=maxstate; i++) { sum=(sum+dp[n][i])%mod; } printf("%lld\n",sum); return 0; }