题目链接。
分析:
作为状态压缩DP入门题,很好。
由题意可知:
1.任意两牛(包括行和列)不能临近
2.牛只能在有草的即值为1的地方
3.不放牛也为一种方案
定义dp[i][s]为第i行状态s下的方案数。
dp[i][s] = ∑(dp[i-1][s']),其中s'为不与s冲突的状态
注意:
因为位运算优先级很低,所以要多加括号。因此
if((cow & (cow<<1)) != 0) return 0; 和 if(cow & (cow<<1) != 0) return 0; 是不一样的
#include <cstdio> #include <cstring> #define MAXN 13 #define MODNUM 100000000 int n, m; int filter[MAXN]; int dp[MAXN][1<<MAXN]; int check(int cow, int grass){ if((cow & grass) != cow) return 0; //检测牛是否都在有草的地方,如果否返回0 if((cow & (cow<<1))) return 0; //该行是否有两牛相邻,有就返回0 return 1; } void solve(){ int i, j, itype, k, ans; memset(dp, 0, sizeof(dp)); dp[0][0] = 1; itype = (1<<m); for(i=1; i<=n; i++){ for(j=0; j<itype; j++){ if(check(j, filter[i])){ for(k=0; k<itype; k++){ if((j&k) == 0){ //保证对于该行j状态与上一行k状态,两行间没有临近的牛 dp[i][j] = (dp[i][j] + dp[i-1][k]) % MODNUM; } } } } } ans = 0; for(i=0; i<itype; i++){ ans = (ans+dp[n][i]) % MODNUM; } printf("%d\n", ans); } int main(){ int i, j, t; scanf("%d %d", &n, &m); for(i=1; i<=n; i++){ filter[i] = 0; for(j=0; j<m; j++){ scanf("%d", &t); filter[i] = (filter[i]<<1)+t; //将每行草地用二进制表示 } } solve(); return 0; }