P3254——DP&&入门
题目
给定一个$n \times m$的$01$矩形,选择其中为$1$的位置,要求互不相邻,问方案数。
解决方案
直接dp因为状态较多,数组很难直接表示出来,我们采用二进制状态压缩存储。
用$dp[i][j]$表示第$i$行$j$状态的方案数,不难写出状态方程$dp[i][j] += dp[i-1][k]$,同时要求$j, k$内部没有相邻的1,$j, k$之间也没有相邻的1,最终答案只需累加第$i$行所有状态下的值.
1 #include<cstdio> 2 using namespace std; 3 4 const int mod = 100000000; 5 int n, m; 6 int maze[15]; 7 int dp[13][1 <<13]; 8 9 bool judge(int i, int j) 10 { 11 if((maze[i] & j) != j) return false; //j只是maze[i]的一部分 12 if(j & (j << 1)) return false; //存在相邻的1 13 return true; 14 } 15 16 void solve() 17 { 18 dp[0][0] = 1; 19 for(int i = 1;i <= n;i++) //枚举每一行 20 { 21 for(int j = 0;j < (1 << m);j++) //枚举第i行所有的状态 22 { 23 if(!judge(i, j )) continue; 24 for(int k = 0;k < (1 <<m);k++) //枚举第i-1行所有的状态 25 { 26 if(j & k) continue; 27 dp[i][j] = (dp[i][j] + dp[i-1][k]) % mod; 28 } 29 } 30 } 31 int ans = 0; 32 for(int i= 0;i < (1 << m);i++) ans = (ans + dp[n][i]) % mod; 33 printf("%d\n", ans); 34 } 35 36 int main() 37 { 38 scanf("%d%d", &n, &m); 39 int tmp; 40 for(int i = 1;i <= n;i++) 41 { 42 for(int j = 0;j < m;j++) 43 { 44 scanf("%d", &tmp); 45 maze[i] = (maze[i] << 1) + tmp; //注意位运算的优先级 46 } 47 } 48 49 solve(); 50 51 return 0; 52 }
参考链接:https://blog.csdn.net/mengxiang000000/article/details/51075506
个性签名:时间会解决一切