【POJ3254】Corn Fields
【题目大意】一个矩阵里有很多格子,每个格子有两种状态,可以放牧和不可以放牧,可以放牧用1表示,否则用0表示,在这块牧场放牛,要求
(1)两个相邻的方格不能同时放牛,即牛与牛不能相邻。问有多少种放牛方案(一头牛都不放也是一种方案)
【解析】根据题意,把每一行的状态用二进制的数表示,0代表不在这块放牛,1表示在这一块放牛。
const int Max_N = 4100 ; const int Mod = 100000000 ; int N , M ; int dp[13][Max_N] ;/*截止到(第i行,状态为j)的中情况数*/ int cannot[13] ; //第i行已经不能放的初始情况 /*判断状态i是否满足左右不相邻*/ int ok(int x){ if(x & (x<<1)) return 0 ; if(x & (x>>1)) return 0 ; return 1 ; } void get_all_states(vector<int> &states){ states.clear() ; for(int i = 0 ; i < (1<<M) ; i++){ if(ok(i)) states.push_back(i) ; } } int DP(){ int i , j , row ; vector<int> state ; get_all_states(state) ; memset(dp , 0 , sizeof(dp)) ; for(i = 0 ; i < state.size() ; i++){ if(state[i] & cannot[1]) continue ; dp[1][state[i]] = 1 ; } for(row = 2 ; row <= N ; row++){ for(i = 0 ; i < state.size() ; i++){ if(state[i] & cannot[row]) continue ; for(j = 0 ; j < state.size() ; j++){ if(state[j] & cannot[row-1]) continue ; if(state[i] & state[j]) //上下不相邻 continue ; dp[row][state[i]] += dp[row-1][state[j]] ; dp[row][state[i]] %= Mod ; } } } int ans = 0 ; for(i = 0 ; i < state.size() ; i++) ans = (ans + dp[N][state[i]] ) % Mod ; return ans ; } int main(){ int x ; while(cin>>N>>M){ for(int i = 1 ; i <= N ; i++){ cannot[i] = 0 ; for(int j = 1 ; j <= M ; j++){ cin>>x ; if(x == 0) cannot[i] |= (1<<(M-j)) ; } } cout<<DP()<<endl ; } return 0 ; }