[★状态压缩DP★] AcWing 291. 蒙德里安的梦想

news/2024/6/16 6:15:42 标签: 动态规划, 算法

输入样例:

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

#include<iostream>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;

typedef long long LL;

const int N = 12, M = 1<<12;
vector<vector<int>> state(M);
bool st[M];
int m,n;
LL f[N][M]; //第一维表示"列", 第二维表示对应的状态(以二进制表示) 

int main()
{
	while((cin>>n>>m) && (m|n))
	{
		//第一次预处理,判断每一种状态留下的连续的空缺数是否都为偶数
		//看第i-2列伸出来的和第i-1列伸出去的是否冲突 
		//对状态数组进行初始化,为之后进一步的处理做铺垫 
		for(int i = 0; i < 1<<n; i++)
		{
			int cnt = 0;
			bool isEven = true; 
			for(int j = 0; j < n; j++)
			{
				if(i>>j & 1){//★ 
					if(cnt & 1){
						isEven = false;
						break; 
					}
				}else{
					cnt ++; 
				}
			}
			if(cnt & 1) isEven = false;
			
			st[i] = isEven;
		}
		
		//第二次预处理
		//判断第i-2列伸出来的和第i-1列伸出去的是否冲突
		for(int j = 0; j < 1<<n; j++)
		{
			state[j].clear();
			for(int k = 0; k < 1<<n; k++)
			{
				if((j&k)==0 && st[ j| k]){//★ 
					//i表示 "列"可行的状态
					//如果第i-1列的状态k和j不冲突则压入state数组中的第j行
					state[j].push_back(k);
				}		
			}
			
		}
		
		//背包,状态压缩 
		memset(f, 0, sizeof(f));
		f[0][0] = 1; 
		for(int i = 1; i <= m; i++){//★ 
			for(int j = 0; j < 1<<n; j++){
				//若 第i列的状态j可行,就进行状态转移
				for(auto k : state[j]){
					// 当前列的方案数就等于之前的第i-1列所有状态k的累加。
					f[i][j] += f[i-1][k];
				}
			}
		} 
		cout << f[m][0] << endl;
	}
	
	return 0;
 } 


 感受:

在第三步正式进行状态压缩之前, 我们努力的方向如下,

★筛除符合以下几种情况的状态(满足任一条即可)

  • 对本列状态进行自我批判(纵向空白能否被2✖1的块填充[计数,判断奇偶])
  • 相邻的列与列之间(其实就是把2^n个状态相互比较)凹凸不匹配,以及两个状态合并后自我批判是否合理(用到 或运算  和  ①中筛出来的st[]数组)


http://www.niftyadmin.cn/n/816707.html

相关文章

[DFS模板题] 全排列以及n-皇后问题

目录 排列数字 利用一维数组标记 利用二进制标记 n-皇后问题 对于关键操作的理解 排列数字 输入样例&#xff1a; 3输出样例&#xff1a; 1 2 3 1 3 2 2 1 3 2 3 1 3 1 2 3 2 1 利用一维数组标记 #include <iostream> using namespace std;const int N 10; int …

Teen Readers【青少年读者】

Teen Readers Teens and younger children are reading a lot less for fun, according to a Common Sense Media report published Monday. 据常识媒体周一发布的报告&#xff0c;为了趣味而阅读青少年少了很多。 While the decline over the past decade is steep for teen r…

[Java 学习笔记] 接口

目录 认识接口 接口继承 default方法 练习:用接口给一个有工资收入和稿费收入的小伙伴算税 认识接口 接口其实是一种特殊的抽象类(没有字段且所有方法全部都是抽象方法) abstract class Person {public abstract void run();public abstract String getName(); } &#x…

ZY的JAVA学习DAY2

JVM&#xff1a;JAVA的虚拟机&#xff0c;用于实现java的跨平台性。 JRE:JAVA的运行环境&#xff0c;包含JVM和JAVA运行的的核心库。 JDK:JAVA开发的工具包。其中包含JRE。 javac.exe: 编译器 java.exe:解释器&#xff08;用于运行&#xff09; cmd 指令&#xff1a;javac命令&…

[BZOJ 1056][HAOI2008]排名系统

传送门 \(\color{green}{solution}\) \(fhq \_treap\)模板题. 对于 \(\) 操作,如果当前人不存在,那么直接加入;如果存在,那么先将他删除,再加入.复杂度\(O(n \log n)\) 对于 \(?\) 操作,如果问人,直接查找名次;如果问名次,先将它前面的\(split\)出去,再把它后面\(10\)个\(spli…

[linux环境] 基于thrift模拟游戏的简易匹配机制(二)

第二天: 利用生产者消费者模型实现傻瓜版匹配机制(不按段位和匹配时间) 前文回顾: [linux环境] 基于thrift模拟游戏的简易匹配机制(一)_☆迷茫狗子的秘密基地☆-CSDN博客thrift官方文档Apache Thrift - Homehttps://thrift.apache.org/我的Git仓库文件 master Knight bit /…

ZY的JAVA学习DAY3

方法 定义一个方法的格式&#xff1a; public static void 方法名称&#xff08;&#xff09;{ 方法体 } 方法名称的命名规则和变量一样&#xff0c;用小驼峰式&#xff0c;即&#xff08;第一个字母小写&#xff0c;后面每个单词首字母大写&#xff09; Jshell 类似于pytho…

[BFS模板题] 数组版/STL版 以及记录路线

目录 题目 ​ 用数组模拟队列 运用queue 拓展:记录路线 题目 输入样例&#xff1a; 5 5 0 1 0 0 0 0 1 0 1 0 0 0 0 0 0 0 1 1 1 0 0 0 0 1 0输出样例&#xff1a; 8 用数组模拟队列 #include <iostream> #include <cstring> #include <algorithm> …