当前位置: 首页 > news >正文

C++ 动态规划 状态压缩DP 蒙德里安的梦想

求把 N×M
的棋盘分割成若干个 1×2
的长方形,有多少种方案。

例如当 N=2,M=4
时,共有 5
种方案。当 N=2,M=3
时,共有 3
种方案。

如下图所示:

2411_1.jpg

输入格式
输入包含多组测试用例。

每组测试用例占一行,包含两个整数 N
和 M

当输入用例 N=0,M=0
时,表示输入终止,且该用例无需处理。

输出格式
每个测试用例输出一个结果,每个结果占一行。

数据范围
1≤N,M≤11
输入样例:
1 2
1 3
1 4
2 2
2 3
2 4
2 11
4 11
0 0
输出样例:
1
0
1
2
3
5
144
51205
在这里插入图片描述
我们需要求出的横向小方格的合法摆放方案数,然后剩下的格子就依次摆放纵向小方格即可。

用 f[i][j] 表示在第 i 列的状态为 j (j是一个二进制数)时的方案数。st[i] 表示状态 i 是否合法,合法的状态是指没有连续奇数个 0 的状态。这个预处理的目的是为了后续的动态规划转移时判断是否可以将当前状态转移到下一状态。

接下来进入动态规划的过程:

首先初始化第一列 f[0][0] = 1,表示在第一列没有任何骨牌时,只有一种覆盖方法。

然后从第二列开始遍历到第 m 列,对于每一列,遍历当前状态 j,以及上一列的状态 k。如果满足以下条件:

j 和 k 没有交集(即 (j & k) == 0),这保证了当前列和上一列没有重叠的部分;
j 和 k 组合在一起的状态是合法的(即 st[j | k] == true),这保证了新状态的合法性。
那么就可以将上一列的方案数加到当前状态上,即 f[i][j] += f[i - 1][k]。

最后,输出 f[m][0],即在最后一列状态为空时的方案数,即为答案。

这样,通过动态规划遍历每一列、每一种状态的组合情况,得到的 f[m][0] 即为棋盘被完全覆盖的方案数。

#include <iostream>
#include <algorithm>
#include <cstring>using namespace std;const int N = 12, M = 1 << N;
long long f[N][M];
bool st[M];int main ()
{int n, m;while(cin>>n>>m, n || m){memset(f, 0, sizeof f);for(int i = 0; i < 1 << n; i ++ ) // 预处理一下所有的状态是不是存在连续奇数个0,枚举所有状态{st[i] = true;int cnt = 0; // 当前这一段0的个数for(int j = 0; j < n; j ++ ) // 枚举每一位if(i >> j & 1) //如果当前位为1,说明上一段0已经截止了{if(cnt & 1) st[i] = false; //说明上段存在奇数个0,不合法cnt = 0; //重新置0,用于下一段判断}else cnt ++;if(cnt & 1) st[i] = false; // 判断剩余的一段0}f[0][0] = 1;for(int i = 1; i <= m; i ++ ) // 枚举每一列for(int j = 0; j < 1 << n; j ++ ) // 枚举当前i列每个状态for(int k = 0; k < 1 << n; k ++ ) // 枚举i - 1列的每个状态if((j & k) == 0 && st[j | k]) // 判断转移条件,首先不能冲突,其次是合法状态(j或k就是当前放完的状态)f[i][j] += f[i - 1][k];printf("%lld\n", f[m][0]); //f[i][j] 表示在第 i 列(从 0 开始计数)且状态为 j 的情况下,合法的排列总数//而题目要求的是在最后一列(第 m 列)且状态为全 0 的情况下的排列总数,因此答案存放在 f[m][0] 中}return 0;
}

相关文章:

  • C++ STL精通之旅:向量、集合与映射等容器详解
  • 【VTKExamples::PolyData】第二十一期 ImplicitPolyDataDistance
  • Flutter学习(八)Flutter_Boost接入
  • 《Docker极简教程》--Docker基础--基础知识(一)
  • elementui上传文件不允许重名
  • Git的一些基本操作
  • MC34063异常发热分析
  • 【初识爬虫+requests模块】
  • 服务器与电脑的区别
  • 酷开科技,打造非凡的生活体验
  • vue-cli引入本地json数据:封装为js文件,无需请求直接读取
  • hive 创建表 字段类型
  • React+Antd实现省、市区级联下拉多选组件(支持只选省不选市)
  • 使用 git 上传文件时,运行 命令 git pull origin 时未成功,出现报错信息
  • Avalonia学习(二十三)-大屏
  • 收藏网友的 源程序下载网
  • avalon2.2的VM生成过程
  • es6要点
  • HTML中设置input等文本框为不可操作
  • Node项目之评分系统(二)- 数据库设计
  • Traffic-Sign Detection and Classification in the Wild 论文笔记
  • 动手做个聊天室,前端工程师百无聊赖的人生
  • 设计模式(12)迭代器模式(讲解+应用)
  • 自制字幕遮挡器
  • gunicorn工作原理
  • Java性能优化之JVM GC(垃圾回收机制)
  • mysql面试题分组并合并列
  • Redis4.x新特性 -- 萌萌的MEMORY DOCTOR
  • ​flutter 代码混淆
  • (4)通过调用hadoop的java api实现本地文件上传到hadoop文件系统上
  • (C#)一个最简单的链表类
  • (NO.00004)iOS实现打砖块游戏(十二):伸缩自如,我是如意金箍棒(上)!
  • (附源码)spring boot基于Java的电影院售票与管理系统毕业设计 011449
  • (附源码)ssm高校运动会管理系统 毕业设计 020419
  • (附源码)ssm经济信息门户网站 毕业设计 141634
  • (力扣记录)235. 二叉搜索树的最近公共祖先
  • (转) SpringBoot:使用spring-boot-devtools进行热部署以及不生效的问题解决
  • (转)http-server应用
  • .NET CLR Hosting 简介
  • .NET Core6.0 MVC+layui+SqlSugar 简单增删改查
  • .Net FrameWork总结
  • .NET 的静态构造函数是否线程安全?答案是肯定的!
  • .NET关于 跳过SSL中遇到的问题
  • .NET建议使用的大小写命名原则
  • .Net开发笔记(二十)创建一个需要授权的第三方组件
  • .NET文档生成工具ADB使用图文教程
  • .one4-V-XXXXXXXX勒索病毒数据怎么处理|数据解密恢复
  • /etc/apt/sources.list 和 /etc/apt/sources.list.d
  • :not(:first-child)和:not(:last-child)的用法
  • @select 怎么写存储过程_你知道select语句和update语句分别是怎么执行的吗?
  • [AIGC] 开源流程引擎哪个好,如何选型?
  • [Avalon] Avalon中的Conditional Formatting.
  • [C++基础]-入门知识
  • [CVPR 2023:3D Gaussian Splatting:实时的神经场渲染]
  • [HarekazeCTF2019]encode_and_encode 不会编程的崽