• P3254——DP&&入门


    题目

    给定一个$n imes 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
    ", 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

      

  • 相关阅读:
    链接工作过程
    编译器工作过程
    图像边缘提取
    剑指32-1 从上到下打印二叉树
    剑指31 栈的压入 弹出序列
    剑指30 包含min函数的栈
    剑指28 对称的二叉树(暂留)
    asp.net core获取当前请求的完整url
    安装启动consul代理,consul后台管理
    asp.net core用命令方式启动项目
  • 原文地址:https://www.cnblogs.com/lfri/p/11171934.html
Copyright © 2020-2023  润新知