状态压缩动态规划(状压DP)详解
0 引子
不要999,也不要888,只要288,只要288,状压DP带回家。你买不了上当,买不了欺骗。它可以当搜索,也可以卡常数,还可以装B,方式多样,随心搭配,自由多变,一定符合你的口味!
在计算机里,整数是以二进制的方式存储的。把状态信息压缩成二进制当成状态进行动态规划,就是状压DP的基本思想。
是不是一脸懵比?别急着关掉文章,接着往下看,你会发现一个新世界。
0.5 状压能解决什么样的问题?
让我们康康这道题:传送门
很容易想到搜索,不是吗?
然而,我们要用更装比 复杂 优美的方式完成这道题。
1.什么是“状态压缩?”
举个例子吧。例如,例题里的“取哪些砝码”这个信息,就可以压缩进一个int整数里。因为,int整数是二进制存储的。大概长这样:
十进制 | 二进制(也就是计算机里实际的状态) |
---|---|
1 | 1 |
2 | 10 |
114514 | 11011111101010010 |
6 | 110 |
我们可以发现,数字是由许多二进制位构成的,要么是0要么是1。
是不是发现了什么?
没错,我们可以用每一位的0和1表示每一个砝码选或者不选!
例如,数字 2 (二进制:10) 就可以表示1号砝码不选,2号砝码选的状态。(因为第1位是0,第2位是1)。
知道了如何压缩,就可以用动态规划的方式求解了。
2.如何枚举出每一个状态?
事实上十分简单,这样就可以:
for(int i=0;i<=(1<<n)-1;i++){
}
(1<<n是把1左移n位的意思。例如,1<<3的二进制就是1000,十进制就是8)
我们来模拟一下\(n=3\)时的情况。
i | i的二进制 |
---|---|
0 | 000 |
1 | 001 |
2 | 010 |
3 | 011 |
4 | 100 |
5 | 101 |
6 | 110 |
7 | 111 |
可以发现,i把所有砝码选取情况都枚举出来了。
3.如何转移?
这个其实因题而异,我就用这道题举例子吧
for(int i=1;i<(1<<n);i++){//枚举。因为i=0就是一个也不选,所以不需要枚举。
int high_bit=0,high_bit_num=0;
for(int j=31;j>=0;j--){//int最多有31位,所以j=31-0。
if((i>>j)&1){//意思是i的第j位是否为1
high_bit=1<<j;
high_bit_num=j;
break;//找到了就退出来
}
}//求出当前方案的最高位
sum[i]=sum[i^high_bit]+a[high_bit_num+1];//转移。因为i是“按顺序”枚举的,所以去掉最高位后的方案一定枚举过了。
//i^high_bit的意思是去掉最高位
cnt[i]=cnt[i^high_bit]+1;
}
(这段代码求的是每种砝码选取方案的重量和与每种砝码选取方案要用多少砝码)
注释写的很详细,我就不再罗嗦了。
4.如果你想A掉这道题
你可以康康我的题解:传送门
但是我还是建议你自己做出来
5.写在最后
状压dp和其它所有算法一样,需要大量的练习才能掌握。
这篇文章写的可能不怎么全面,欢迎在评论区提问或指出。另外,不要吊死在一棵树上,多康康别人的文章吧。
状态压缩动态规划(状压DP)详解的更多相关文章
- 状态压缩动态规划 状压DP
总述 状态压缩动态规划,就是我们俗称的状压DP,是利用计算机二进制的性质来描述状态的一种DP方式 很多棋盘问题都运用到了状压,同时,状压也很经常和BFS及DP连用,例题里会给出介绍 有了状态,DP就比 ...
- 状态压缩dp 状压dp 详解
说到状压dp,一般和二进制少不了关系(还常和博弈论结合起来考,这个坑我挖了还没填qwq),二进制是个好东西啊,所以二进制的各种运算是前置知识,不了解的话走下面链接进百度百科 https://baike ...
- 状压DP详解+题目
介绍 状压dp其实就是将状态压缩成2进制来保存 其特征就是看起来有点像搜索,每个格子的状态只有1或0 ,是另一类非常典型的动态规划 举个例子:有一个大小为n*n的农田,我们可以在任意处种田,现在来描述 ...
- 状压DP详解(位运算)
前言: 状压DP是一种非常暴力的做法(有一些可以排除某些状态的除外),例如dp[S][v]中,S可以代表已经访问过的顶点的集合,v可以代表当前所在的顶点为v.S代表的就是一种状态(二进制表示),比如 ...
- hihoCoder 1044 : 状态压缩·一 状压dp
思路:状态压缩,dp(i, j)表示考虑前i个数且[i-m+1, i]的选择情况为j.如果要选择当前这个数并且,数位1的个数不超过q,则dp[i+1][nex] = max(dp[i+1][nex], ...
- hihocoder #1044 : 状态压缩·一 状压DP
http://hihocoder.com/problemset/problem/1044 可以看出来每一位的选取只与前m位有关,我们把每个位置起始的前m位选取状态看出01序列,就可以作为一个数字来存储 ...
- 动态规划---状压dp
状压dp,就是把动态规划之中的一个个状态用二进制表示,主要运用位运算. 这里有一道例题:蓝书P639猛兽军团1 [SCOI2005]互不侵犯 题目: 题目描述 在N×N的棋盘里面放K个国王,使他们互不 ...
- 【bzoj3195】【 [Jxoi2012]奇怪的道路】另类压缩的状压dp好题
(上不了p站我要死了) 啊啊,其实想清楚了还是挺简单的. Description 小宇从历史书上了解到一个古老的文明.这个文明在各个方面高度发达,交通方面也不例外.考古学家已经知道,这个文明在全盛时期 ...
- 【状压DP】bzoj1087 互不侵犯king
一.题目 Description 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上.下.左.右,以及左上.左下.右上.右下八个方向上附近的各一个格子,共8个格子. I ...
随机推荐
- PHP date_isodate_set() 函数
------------恢复内容开始------------ 实例 设置 2013 年第 5 周的 ISO 日期: <?php$date=date_create();date_isodate_s ...
- PDO::rollBack
PDO::rollBack — 回滚一个事务(PHP 5 >= 5.1.0, PECL pdo >= 0.1.0) 说明 语法 bool PDO::rollBack ( void )高佣联 ...
- day20:正则表达式
单个字符的匹配 findall(正则表达式,字符串) 把符合正则表达式的字符串存在列表中返回 预定义字符集(8) \d 匹配数字 \D 匹配非数字 \w 匹配数字字母下划线 \W 匹配非数字或字母或下 ...
- 7.9 NOI模拟赛 数列 交互 高精 字符串
这是交互题 也是一个防Ak的题目 4个\(subtask\) 需要写3个不尽相同的算法. 题目下发了交互程序 所以调试的时候比较方便 有效防止\(CE\). 题目还有迷糊选手的点 数字位数为a 范围是 ...
- 记录一次线上实施snmp
公司要实施一个部级的项目,我们公司的提供的产品要对接下客户的一个平台监控平台,该监控平台使用snmp,我们公司的产品不支持snmp,所以由我负责在现网实施snmp,记录这次现网 一.生成编译规则 1. ...
- Java和Scala容器转换
参考:https://blog.csdn.net/dymkkj/article/details/77921573 Java和Scala互操作的一个重要的内容就是容器的转换,容器是一个语言的数据结构,表 ...
- 畅购商城(四):Lua、OpenResty、Canal实现广告缓存与同步
好好学习,天天向上 本文已收录至我的Github仓库DayDayUP:github.com/RobodLee/DayDayUP,欢迎Star,更多文章请前往:目录导航 畅购商城(一):环境搭建 畅购商 ...
- 从零写一个Asp.net core手脚架(模型验证)
一个asp.net core项目,一定包含了各种的实体,在RESTful api里面,有很多的参数传递,不建立实体则大量的参数需要自定验证正确性,并且Action上面会写的密密麻麻的参数 在asp.n ...
- 2、Java 基础语法标识符、修饰符、变量、 数组、枚举、关键字
Java 基础语法 一个 Java 程序可以认为是一系列对象的集合,而这些对象通过调用彼此的方法来协同工作.下面简要介绍下类.对象.方法和实例变量的概念. 对象:对象是类的一个实例,有状态和行为.例如 ...
- C++ 的字符串反转
C++ 的字符串反转 方法一: 使用 algorithm 中的 reverse 函数: // reverse 函数的定义(在 std 名称空间中) template<class BidirIt& ...