## 一.知识
1.我们知道计算机中数据由二进制数存储,一个二进制数的一位就是计算机中数据的最小单位bit,我们有一种运算符可直接对二进制数进行位运算,所以它的速度很快。

2.C++中的位运算符有6

        &     与运算        同1得1
        |       或运算       有1得1   
        ^      异或运算    不同得1
        ~      非运算       取反
       >>     右移运算   
      <<      左移运算

3. 按位取反举例
补码的补码就是原码,在计算机中存储全是补码,
十进制数1的二进制补码为:00000001
取反后补码为:11111110
求这个补码的原码:10000010(屏幕上显示都是原码-2)
所以1取反后等于-2

4. 在补码下,每个数值都有唯一的表示方式,并且任意两个数值做加减法运算,都等价于在32位补码下做**最高位不进位**的二进制加减法运算。发生算术溢出时,相当于自动对2^32^取模。所以要注意两个大整数相加有可能是负数。

## 二.成对变换
我们通过计算可以发现,对于非负整数n:
当n为偶数时,n ^ 1 等于 n+1
当n为奇数时,n ^ 1 等于 n-1
因此0和1,2和3,4和5,这些数对都是关于异或“成对变换”,这个性质经常用于图论,可以通过异或运算获得当前边的反向边编号。但为了安全起见,最好边的编号最好从2开始。

## 三.lowbit运算
lowbit(n) 取出非负整数n在二进制表示下最低位的1以及后边的0构成的数值。
lowbit(n) = n & (~n+1) = n & -n
lowbit 是树状数组的核心操作。
lowbit 配合hash可以找到整数二进制表示下所有是1的位,所花费的时间与1的个数同级。

## 四.二进制状态压缩

二进制状态压缩,是指将一个长度为m的bool数组用一个m位二进制整数表示并存储的方法。利用下列位运算操作可以实现原bool数组中对应下标元素的存取。

操作| 运算
---|---
取出整数n在二进制表示下的第k位                          (n>>k) & 1
取出整数n在二进制表示下第0~k-1位(后k位)       n & ((1<<k)-1)
把整数n在二进制表示下的第k位取反                       n ^ (1<<k)
对整数n在二进制表示下的第k位赋值为1                 n \| (1<<k)
对整数n在二进制表示下的第k位赋值为0                 n & (~(1<<k))

这种方法运算简便,并且节省了程序运行的时间和空间。当m不大时,可以直接使用一个整数类型存储。当m较大时,可以使用若干个整数类型(int数组),也可以直接利用bitset实现。

#### 例题
给定一张n(n<=20)个点的带权无向图,点从0~n-1标号,求起点0到终点n-1的最短hamilton路径。hamilton路径的定义是从0到n-1不重不漏地经过每个点恰好一次。([洛谷1171]

扩展题目:[POJ2288 Islands and Bridges]

思路点拨: 
很容易想到一种朴素的做法,就是枚举n个点的全排列,计算路径长度,取最小值,时间复杂度为O(n*n!),可以使用状态压缩dp将其优化到O(n^2^*2^n)

在任意时刻,要表示出哪些点被走过,哪些点没有被走过,可以用一个n位二进制数,若其第i位(0<=i<n)为1,则表示第i个点已经被经过,反之未被经过。在任意时刻还需要知道当前所处的位置,因此使用F[i,j](0<=i<2^n,0<=j<n)表示点被经过的状态对应的二进制数为i,且目前处于点j时的最短路径。

初始值F[1,0],即只经过了点0(i只有第0位是1),目前处于起点0,最短路径长度为0。方便起见,将F的其他值设为极大值,目标状态为F[(1<<n)-1,n-1],即经过所有点(i的所有位都是1),处于终点n-1的最短路。

在任意时刻,有公式F[i,j]=min{F[i ^
(1<<j),k]+weight(k,j)},0<=k<n并且((i>>j)&1)=1,即当前时刻“被经过的点的状态”对应的二进制数为i,处于点j。因为j只能恰被经过1次,所以一定是刚刚经过的,故在上一时刻“被经过的点的状态”对应的二进制数的第j位应该赋值为0,也就是i^(1<<j)。另外,上一时刻所处的位置可能是i^(1<<j)中任意一个是1的位置k,从k走到j需要weight(k,j),可以考虑取所有这样的k取最小值。
int f[1<<20][20];
int main()
{
    memset(f,0x3f,sizeof f);
    f[1][0]=0;
    for(int i=1;i<(1<<n);i+=2)

    {
        for(int j=0;j<n;j++)
        {
            if(!((i >> j) & 1))
continue; //当前i状态下,根本没有走过j
            for(int k=0;k<n;k++)
            {
                if(j==k) continue;
                if(!(i>>k & 1))
continue; //上一次状态,根本没有走过k,就更不可能从k转移到j
                f[i][j]=min(f[i][j],f[i^(1<<j)][k]+weight[k][j]);
            }
        }
    }
    cout << f[(1<<n)-1][n-1];
// 所有点走完,最后停在n-1点上
}

状压dp之位运算的更多相关文章

  1. 状压DP总结

    状态压缩就是将一行的状态压成一个二进制数,这个数的二进制形式反映了这一行的情况 比如0100111的意义为:这一排的第一个数没被使用,第二个被占用了,第三四个没被占用,第五六七个被占用 我们知道位运算 ...

  2. 状压DP详解(位运算)

    前言: 状压DP是一种非常暴力的做法(有一些可以排除某些状态的除外),例如dp[S][v]中,S可以代表已经访问过的顶点的集合,v可以代表当前所在的顶点为v.S代表的就是一种状态(二进制表示),比如 ...

  3. 【POJ3254】Corn Fields 状压DP第一次

    !!!!!!! 第一次学状压DP,其实就是运用位运算来实现一些比较,挺神奇的.. 为什么要发“!!!”因为!x&y和!(x&y)..感受一下.. #include <iostre ...

  4. 【状压DP】bzoj1087 互不侵犯king

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

  5. BZOJ 1087 题解【状压DP】

    1087: [SCOI2005]互不侵犯King Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 3112  Solved: 1816[Submit][ ...

  6. HITOJ 2662 Pieces Assignment(状压DP)

    Pieces Assignment My Tags   (Edit)   Source : zhouguyue   Time limit : 1 sec   Memory limit : 64 M S ...

  7. FZU 1025 状压dp 摆砖块

    云峰菌曾经提到过的黄老师过去讲课时的摆砖块 那时百度了一下题目 想了想并没有想好怎么dp 就扔了 这两天想补动态规划知识 就去FZU做专题 然后又碰到了 就认真的想并且去做了 dp思想都在代码注释里 ...

  8. 状压DP

    今天稍微看了下状压DP,大概就是这样子的,最主要的就是位运算, i and (1<<k)=0 意味着i状态下没有 k : i and (1<<k)>0 意味着i状态下有 ...

  9. POJ 3254 (状压DP) Corn Fields

    基础的状压DP,因为是将状态压缩到一个整数中,所以会涉及到很多比较巧妙的位运算. 我们可以先把输入中每行的01压缩成一个整数. 判断一个状态是否有相邻1: 如果 x & (x << ...

随机推荐

  1. 第N个丑数

    #include <bits/stdc++.h> using namespace std; #define ll long long /* 把只包含质因子2.3和5的数称作丑数(Ugly ...

  2. [转帖]征服诱人的Vagrant!

    征服诱人的Vagrant! https://www.cnblogs.com/hafiz/ 一.背景 ​ 最近要开始深入学习分布式相关的东西了,那第一步就是在自己的电脑上安装虚拟机,以前在Windows ...

  3. HTML5+规范:nativeUI(管理系统原生界面)

    nativeUI管理系统原生界面,可用于弹出系统原生提示对话框窗口.时间日期选择对话框.等待对话框等. 1.方法 1.1.actionSheet: 弹出系统选择按钮框 void plus.native ...

  4. mysql 查询导出 excel 中文乱码 解决 --default-character-set=gbk

    mysql  --default-character-set=gbk -uroot -p   -D open_fusion -e  " select * from table1  " ...

  5. Java爬虫https网页内容报错SSLHandshakeException信任(忽略)所有SSL证书

    javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building f ...

  6. C# 运行流程

    转载  https://www.cnblogs.com/qcloud1001/p/9816956.html 从编译原理说起 一句话介绍编译器:编译器是将用某种程式语言写成的源代码(源语言),转换成另一 ...

  7. EFCore自动迁移

    2019/05/14,EFCore 2.2.4 有两种方式: 使用Migrate()方法 if (DbContext.Database.GetPendingMigrations().Any()) { ...

  8. C# vb .net实现宝丽来效果滤镜

    在.net中,如何简单快捷地实现Photoshop滤镜组中的宝丽来效果呢?答案是调用SharpImage!专业图像特效滤镜和合成类库.下面开始演示关键代码,您也可以在文末下载全部源码: 设置授权 第一 ...

  9. How to do SSH Tunneling (Port Forwarding)

    How to do SSH Tunneling (Port Forwarding) In this post we will see how ssh works?, what is SSH tunne ...

  10. Tomcat组件梳理--Catalina

    Tomcat组件梳理--Catalina 1.定义和功能 Catalina是Tomcat的核心组件,是Servlet容器,Catalina包含了所有的容器组件,其他模块均为Catalina提供支撑.通 ...