【动态规划】状态压缩DP(状压dp)
还在更新ing
一、引入
在动态规划状态设计中,若状态是一个集合,例如
这种将集合作为整数记录状态的一类算法叫作状态压缩 DP 。在状态压缩 DP 中,状态的设计直接决定了程序的效率或者代码长短。我们需要根据问题分析本质,才能更好地找出恰当的状态表示、状态转移方程和边界条件。
二、二进制 & 位运算
尽管用了一个十进制数据储存二进制状态,当因为操作系统是二进制的,所以在编译器中也可采用位运算解决这个问题。
1、基本位操作运算符
在状态压缩 DP 中广泛运用位运算操作,常见的位运算如下 :
A |
B |
~A (差) |
A ^ B (异或) |
||
---|---|---|---|---|---|
0 | 0 | 1 | 0 | 0 | 0 |
0 | 1 | 1 | 0 | 1 | 1 |
1 | 0 | 0 | 0 | 1 | 1 |
1 | 1 | 0 | 1 | 1 | 0 |
如果
例如:
~
另外,还有两个位移操作运算符左移(<<)
、右移(>>)
。
如:A<<B
,表示
注意,对二进制数,位数高低为从右到左依次为
所以我们可以认为 A<<B
等价于 A>>B
等价于
2,常见的操作有:
去掉最后一位 ( x >> 1
在最后加一个 x << 1
在最后加一个 x << 1 | 1
把最后一位变成 x | 1
把最后一位变成 x | 1 - 1
最后一位取反 ( x ^ 1
把右数第 x | (1 << (k - 1))
把右数第 x & not (1 << (k - 1))
右数第 x ^ (1 << (k - 1))
取末三位 ( x & 7
取末 x & (1 << k - 1)
取右数第 x >> (k - 1) & 1
把末 x | (1 << k-1)
末 x ^ (1 << k-1)
把右边连续的 x & (x + 1)
把右起第一个 x | (x + 1)
把右边连续的 x | (x - 1)
取右边连续的 (x ^ (x + 1)) >> 1
3、表示集合(状态压缩)
有时我们用
常见的操作有:
并集操作 A | B
交集操作 A & B
集合的差 A & ~ B
补集 -1 ^ A
(
加入第 A = A | (1 << (i - 1))
删除第 A = A & ~ (1 << (i - 1))
判断第 (A & (1 << (i - 1))) != 0
4、lowbit
求最低位的
lowbit(int x) {
return x&(-x);
}
三、实现流程
状态压缩 DP 大可分为两类 :
- 棋盘式(基于连通性)DP
- 集合式 DP
状态压缩dp三部曲:
- 考虑如何状态压缩
- 确定状态表示和状态转移方
- 根据实际问题确定筛选条件
例题引入
著名的旅行商问题( Traveling Salesman Problem,TSP )指一个旅行商从一个城市出发,经过每一个城市一次且只有一次回到原来的地方,要求经过的距离最短。
TSP 问题是一个 NP 难题,目前没有多项式时间的高效算法。若采用搜索+剪枝,则该算法的时间复杂度为
假设已访问的节点集合为
I. 状态表示
II. 状态转移方程
若当前
III. 临界条件
Code
void Traveling() { //计算f[S][u]
f[(1<<n)-1][0]=0; //1<<n一定要加括号(别问我为什么)
for(int S=(1<<n)-2;S>=0;S--) {
for(int u=0;u<n;u++) {
for(int v=0;v<n;v++) {
if((u!=0&&!(S>>u&1))||w[u][v]==inf) continue; //可以加约束条件,不加太多状态
if(!(S>>v&1)&&f[S][u]>f[(S|1<<v)][v]+w[u][v]) {
f[S][u]=f[(S|1<<v)][v]+w[u][v];
path[S][u]=v; //记录后继节点
}
}
}
}
}
训练 1 :[USACO06NOV] Corn Fields G
源自 洛谷 P1879 [USACO06NOV] Corn Fields G
题目描述
农场主
遗憾的是,有些土地相当贫瘠,不能用来种草。并且,奶牛们喜欢独占一块草地的感觉,于是
输入格式
第一行:两个整数
第
输出格式
一个整数,即牧场分配总方案数除以
样例 #1
样例输入 #1
2 3
1 1 1
0 1 0
样例输出 #1
9
题解
I. 分析题意
本题求在值为
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!