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

  

posted @ 2019-07-11 18:50  Rogn  阅读(278)  评论(0编辑  收藏  举报