状压DP详解(位运算)
前言:
状压DP是一种非常暴力的做法(有一些可以排除某些状态的除外),例如dp[S][v]中,S可以代表已经访问过的顶点的集合,v可以代表当前所在的顶点为v。S代表的就是一种状态(二进制表示),比如 (11001)2 代表在二进制中{0,3,4}三个顶点已经访问过了,(11001)2 代表的十进制数就是25 ,所以当S为25的时候其实就是代表已经访问过了{0,3,4}三个顶点,那假如一共有5个顶点(标号为01234)的话,所有的顶点都访问完毕应该S为什么呢?是 (11111)2。
那么,在状态转移的过程中我们势必要对十进制数转化为二进制数的每一个的位数进行一些操作。下面,列举了一些位运算的操作。

对于上面的一些操作举例一些
就如之上的 (11001)2 来说是已经访问了0,3,4三个顶点,当我接下去要访问顶点2的话可以有以下操作:1.看看第3位是什么?那么选择取出二进制数x的第k位,y = x >>(k-1) & 1,y = (110)2 & 1 = 0,2.把第3位变为1,y = x | (1<<(k-1)),y = (11001)2 | (100)2 = (11101)2,所以顶点2访问完毕,加入到集合S中也结束了,此时S为(11101)2 = 29。
接下去就可以开始讲一些例题了。最经典的就是白皮书上的tsp问题。
tsp问题
题意:假设有一个旅行商人要拜访N个城市,他必须选择所要走的路径,路径的限制是每个城市 只能拜访一次,而且最后要回到原来出发的城市,要求路径的总和最小。其中,2<=N<=15
思路:首先我们试着去设计状态,假设现在已经访问过的顶点的集合为S,当前所在顶点为v, 用dp[S][v]表示从v出发还有访问剩余的所有顶点,最终返回到顶点0的路径总和最小值。从v出发可以到任意一个还未访问过的顶点,边界就是访问完所有顶点并且返回到顶点0。
递推式为
dp[V][0] = 0;(边界)
dp[S][v] = min{dp[S∪{u}][u] + d[u][v] | u不属于S}
先通过记忆化搜索来看一下code
// s: 已经访问过的节点状态 v: 出发位置
int dfs(int s, int v)
{
if(dp[s][v]>=)
return dp[s][v];
if(s==(<<n)- && v==) //已经访问过所有的节点并且再次回到了0起点
return dp[s][v]=;
int ans=INF;
for(int u=;u<n;u++)
if(!(s>>(u &))) // 如果u这位是0(代表没有走过的话)就走u这个节点
ans=min(ans, dfs(s | (<<u), u)+mp[v][u]); //dfs中第一个参数表示第u位变成1后的二进制数
return dp[s][v]=ans;
}
int main()
{
memset(dp, -, sizeof(dp));
printf("%d\n", dfs(, ));
return ;
}
但是在这个问题中,对于任意两个整数i和j,如果他们对应的集合满足S(i)包含于S(j),就有i<=j,因此我们可以写成循环的方式。
int dp[<<maxn][maxn]; void solve()
{
for(int S = ; S < <<n; S++)
{
fill(dp[S],dp[S]+n,INF); //初始化
}
dp[(<<n) - ][] = ; //边界条件
//之前的记忆化搜索转换为递推式
for(int S = (<<n) - ; S >= ; S--)
{
for(int v = ; v < n; v++)
{
for(int u = ; u < n; u++)
{
if(!(S>>u&)){ //如果u不属于S集合
dp[S][v] = min(dp[S][v],dp[S|<<u][u]+d[v][u]);
}
}
}
}
printf("%d\n",dp[][]);
}
这样子,一个状压DP的板子差不多就出来了。
状压DP详解(位运算)的更多相关文章
- 状态压缩dp 状压dp 详解
说到状压dp,一般和二进制少不了关系(还常和博弈论结合起来考,这个坑我挖了还没填qwq),二进制是个好东西啊,所以二进制的各种运算是前置知识,不了解的话走下面链接进百度百科 https://baike ...
- 状压DP详解+题目
介绍 状压dp其实就是将状态压缩成2进制来保存 其特征就是看起来有点像搜索,每个格子的状态只有1或0 ,是另一类非常典型的动态规划 举个例子:有一个大小为n*n的农田,我们可以在任意处种田,现在来描述 ...
- 状态压缩动态规划(状压DP)详解
0 引子 不要999,也不要888,只要288,只要288,状压DP带回家.你买不了上当,买不了欺骗.它可以当搜索,也可以卡常数,还可以装B,方式多样,随心搭配,自由多变,一定符合你的口味! 在计算机 ...
- Codeforces 895C - Square Subsets 状压DP
题意: 给了n个数,要求有几个子集使子集中元素的和为一个数的平方. 题解: 因为每个数都可以分解为质数的乘积,所有的数都小于70,所以在小于70的数中一共只有19个质数.可以使用状压DP,每一位上0表 ...
- luoguP6622 [省选联考 2020 A/B 卷] 信号传递(状压dp)
luoguP6622 [省选联考 2020 A/B 卷] 信号传递(状压dp) Luogu 题外话: 我可能是傻逼, 但不管我是不是傻逼, 我永远单挑出题人. 题解时间 看数据范围可以确定状压dp. ...
- 状压DP入门详解+题目推荐
在动态规划的题型中,一般叫什么DP就是怎么DP,状压DP也不例外 所谓状态压缩,一般是通过用01串表示状态,充分利用二进制数的特性,简化计算难度.举个例子,在棋盘上摆放棋子的题目中,我们可以用1表示当 ...
- 状压DP初探·总结
2018过农历新年这几天,学了一下状态压缩动态规划,现在先总结一下. 状态压缩其实是一种并没有改变dp本质的优化方法,阶段还是要照分,状态还是老样子,决策依旧要做,转移方程还是得列,最优还是最优, ...
- 状压入门--bzoj1087: [SCOI2005]互不侵犯King【状压dp】
Description 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上 左下右上右下八个方向上附近的各一个格子,共8个格子. Input 只有一行, ...
- 状压DP : [USACO06NOV]玉米田
玉米田 内存限制:128 MiB 时间限制:1000 ms 标准输入输出 题目类型:传统 评测方式:文本比较 题目描述 农场主John新买了一块长方形的新牧场,这块牧场被划分成M行N列(1 ≤ M ≤ ...
随机推荐
- agc001E - BBQ Hard(dp 组合数)
题意 题目链接 Sol 非常妙的一道题目. 首先,我们可以把\(C_{a_i + b_i + a_j + b_j}^{a_i + a_j}\)看做从\((-a_i, -b_i)\)走到\((a_j, ...
- The fool doth think he is wise, but the wise man knows himself to be a fool.
The fool doth think he is wise, but the wise man knows himself to be a fool.愚者总自以为聪明,智者则有自知之明.
- Cocos2D-HTML5 Android项目编译
首先要有 Eclipse 和 ADT.CDT.Android SDK.Android NDK.新建一个文件MoonWar_Apk.cmd,将以下代码拷贝其中,双击之即可. set EngineHome ...
- 自定义 sql Split函数 / 自定义mp_helptext查看存储
1. 分割函数: --Split 表函数将一个字符串按指定分隔符进行分割,返回一个表. create function split( ),--待分割字符串 )--分割符 ))) as begin ) ...
- .net core 2.0 WIndows IIS下发布(WIN 10环境)
最近在做练习,发布.net core webapi在本机IIS上,使用.net core的文件系统发布到IIS后,出现错误 500.19 观察了下页面如下 查阅资料才知道是少安装了一个DotNetCo ...
- 幻灯片的JQuqey的制作效果,只要几行代码
使用jquery.KinSlideshow.js就可以很轻松的实现幻灯片效果 htm代码: [html] <div id="focusNews" style=&quo ...
- 2017.11.4 JavaWeb-----基于JavaBean+JSP求任意两数代数和(改进的在JSP页面中无JSP脚本代码的)+网页计数器JavaBean的设计与使用
修改后的JSP中不含有JSP脚本代码这使得JSP程序的清晰性.简单 1.设计JavaBean 的Add.java 类 package beans; public class Add { private ...
- 【转】css行高line-height的一些深入理解及应用
一.前言 前两天在腾讯ISD团队博客上看到一篇翻译的文章“深入理解css 行高”,是个不错的文章,学到了不少东西,建议您看看. 这里,我也要讲讲我对line-height的一些理解,所讲解的东西绝大多 ...
- Java-笔记1
/* 对第一个java程序进行总结 1. java程序编写-编译-运行的过程 编写:我们将编写的java代码保存在以".java"结尾的源文件中 编译:使用javac.exe命令编 ...
- war和war exploded的区别
是选择war还是war exploded 这里首先看一下他们两个的区别: (1)war模式这种可以称之为是发布模式,看名字也知道,这是先打成war包,再发布: (2)war exploded模式是直接 ...