前言:

状压DP是一种非常暴力的做法(有一些可以排除某些状态的除外),例如dp[S][v]中,S可以代表已经访问过的顶点的集合,v可以代表当前所在的顶点为v。S代表的就是一种状态(二进制表示),比如  (11001)2  代表在二进制中{0,3,4}三个顶点已经访问过了,(11001)代表的十进制数就是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)& 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详解(位运算)的更多相关文章

  1. 状态压缩dp 状压dp 详解

    说到状压dp,一般和二进制少不了关系(还常和博弈论结合起来考,这个坑我挖了还没填qwq),二进制是个好东西啊,所以二进制的各种运算是前置知识,不了解的话走下面链接进百度百科 https://baike ...

  2. 状压DP详解+题目

    介绍 状压dp其实就是将状态压缩成2进制来保存 其特征就是看起来有点像搜索,每个格子的状态只有1或0 ,是另一类非常典型的动态规划 举个例子:有一个大小为n*n的农田,我们可以在任意处种田,现在来描述 ...

  3. 状态压缩动态规划(状压DP)详解

    0 引子 不要999,也不要888,只要288,只要288,状压DP带回家.你买不了上当,买不了欺骗.它可以当搜索,也可以卡常数,还可以装B,方式多样,随心搭配,自由多变,一定符合你的口味! 在计算机 ...

  4. Codeforces 895C - Square Subsets 状压DP

    题意: 给了n个数,要求有几个子集使子集中元素的和为一个数的平方. 题解: 因为每个数都可以分解为质数的乘积,所有的数都小于70,所以在小于70的数中一共只有19个质数.可以使用状压DP,每一位上0表 ...

  5. luoguP6622 [省选联考 2020 A/B 卷] 信号传递(状压dp)

    luoguP6622 [省选联考 2020 A/B 卷] 信号传递(状压dp) Luogu 题外话: 我可能是傻逼, 但不管我是不是傻逼, 我永远单挑出题人. 题解时间 看数据范围可以确定状压dp. ...

  6. 状压DP入门详解+题目推荐

    在动态规划的题型中,一般叫什么DP就是怎么DP,状压DP也不例外 所谓状态压缩,一般是通过用01串表示状态,充分利用二进制数的特性,简化计算难度.举个例子,在棋盘上摆放棋子的题目中,我们可以用1表示当 ...

  7. 状压DP初探·总结

    2018过农历新年这几天,学了一下状态压缩动态规划,现在先总结一下.   状态压缩其实是一种并没有改变dp本质的优化方法,阶段还是要照分,状态还是老样子,决策依旧要做,转移方程还是得列,最优还是最优, ...

  8. 状压入门--bzoj1087: [SCOI2005]互不侵犯King【状压dp】

    Description 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上 左下右上右下八个方向上附近的各一个格子,共8个格子. Input 只有一行, ...

  9. 状压DP : [USACO06NOV]玉米田

    玉米田 内存限制:128 MiB 时间限制:1000 ms 标准输入输出 题目类型:传统 评测方式:文本比较 题目描述 农场主John新买了一块长方形的新牧场,这块牧场被划分成M行N列(1 ≤ M ≤ ...

随机推荐

  1. PHP迭代器 Iterator

    Iterator是PHP自带的迭代器接口. 实现该接口的类必须实现该接口的方法,以便能够使用foreach进行输出迭代后的数据. interface Iterator extends Traversa ...

  2. sass随笔

    一.前期准备       sass基于ruby     (1)   安装ruby  从http://rubyinstaller.org/downloads/下载 双击下载的程序进行安装,勾选如下图的选 ...

  3. 超链接导致window.location.href失效的解决办法

    通常我们采用 window.location.href 执行页面间的跳转,比如下面的语句 window.location.href = 'https://www.baidu.com/'; 一般执行上面 ...

  4. JSON 与 XML基本了解

    简单了解JSON 和 XML ,以及他们的区别: JSON:是一种轻量级的数据交换格式,ECMA(欧洲计算机制造商协会)的一个子集:   优点:轻量级.占用宽带小.易于人的阅读和编写,便于js解析,支 ...

  5. scss牛刀小试:解决css中适配浏览器前缀问题

    在css中为适配浏览器,新特性总加 -webkit,-o, -moz 来适配浏览器,写的烦心,看着也臃肿,让css可读性降低,下面以阴影为例,如何使用scss让我们的css看起来更简洁. 本人使用的I ...

  6. List之Sort使用

    void TestListSort(){ List<string> st = new List<string> (); st.Add ("abcd"); s ...

  7. windows10家庭中文版升级专业版或企业版简单方便的操作方法

    以管理员的身份运行cmd 1 ,升级到专业版输入:slmgr /ipk W269N-WFGWX-YVC9B-4J6C9-T83GX 输入slmgr.vbs -skms zh.us.to 激活 2, 升 ...

  8. jshint-eclipse: JavaScript Code Quality Plugin for Eclipse

    https://blog.oio.de/2012/03/26/jshint-eclipse-javascript-code-quality-plugin-for-eclipse/   techscou ...

  9. 笨办法学Python(十)

    习题 10: 那是什么? 在习题 9 中我你接触了一些新东西.我让你看到两种让字符串扩展到多行的方法.第一种方法是在月份之间用 \n (back-slash n )隔开.这两个字符的作用是在该位置上放 ...

  10. 《孵化Twitter》:Twitter创始人勾心斗角史,细节披露程度令人吃惊

    本书详细讲述twitter的发展史.感觉基本上是一部创始人从朋友变敌人,勾心斗角的历史.Twitter本身的产品发展反而相对比较简单. 书中披露了许多email.谈话.会议的细节,作者说这些是数百个小 ...