一、位运算
二、递推与递归
位运算:二进制做基础,位运算给了我们一个操作简单的计算机。
位运算基础:
&:按位与,如果两个相应的二进制都为1,则该位值为1,否则为0.
|:按位或,两个相应的二进制位中只要有一个为1,则该位的值为1;
^:按位异或,若参加运算的两个数的值相同,则该值为1,否则为0;
~:取反,一元运算符,用来对二进制数按位取反,1-0,0-1;
<<:左移,用来将一个数的个二进制位全部左移N位,右边补0;
>>:右移,用来将一个数的个二进制位全部右移N位,移到右端的低位被舍弃,对于无符号数,高位补0.
原码、补码、反码:
真值:第一位表示符号位:最高位1表示负值,0表示正值,
原码:符号位加上真实值的绝对值,第一位表示符号,其余位表示值
例如:8位的二进制数
[+1]原码;0000 0001
[-1]原码:1000 0001
所以,8位的二进制数的范围为【1111 1111,0111 1111】[-127.127];
反码:正数的反码是其本身,负数的反码是在其原码的基础上,符号位不变,其余位取反;
例如:
[+1]=[0000 0001]原=[0000 0001]反
[-1]=[1000 0001]原=[1111 1110]反
对于负数,通常也需要转换成原码进行计算;
补码:正数的补码是其本身,负数的补码是在原码的基础上,符号位不变,其余各位取反,最后+1,(反码的基础上+1);
例如:
[+1]=[0000 0001]原=[0000 0001]反=[0000 0001]补
[-1]=[1000 0001]原=[1111 1110]反=[1111 1111]补
二进制状态压缩:将一个长度为m的bool数组,用一个m位的二进制整数表示并储存的方法;
例题: 链接:91. 最短Hamilton路径 - AcWing题库
#include
using namespace std;
const int N = 20,M = 1 << N;
//解释一下1 << N:因为i是二进制数,表示从0到当前点的状态,所以每个点都有两个状态0和1,所以是2的N次方
int n;
int w[N][N]; //每条边的权重
int f[M][N]; //表示从0到j,走过的点是i的所有路径
int main()
{
scanf("%d",&n);
for(int i = 0;i < n;i ++)
{
for(int j = 0;j < n;j ++)
{
scanf("%d",&w[i][j]);
}
}
memset(f,0x3f,sizeof f);
f[1][0] = 0; //0为起点,所以为0
for(int i = 0;i < 1 << n;i ++)
{ //i表示的所有的状态
for(int j = 0;j < n;j ++)
{ //j表示走到的哪一点
if(i >> j & 1){ //如果i的j为1,说明到达过这个点
for(int k = 0;k < n;k ++)
{ //k表示走到j这个点之前,以k为终点的最短距离
if((i - (1 << j)) >> k & 1)
{ //i除去j这个点后包含k这个点
f[i][j] = min(f[i][j],f[i - (1 << j)][k] + w[k][j]); //状态转移,前面图1有详细讲解哦~
}
}
}
}
}
printf("%d\n",f[(1 << n) - 1][n - 1]); //输出答案
//(1 << n) - 1表示:有n个1,也就是所有的点都走完了
//n - 1表示:终点
//合起来就是所有的点都走完的方案,最后落脚在n - 1这个点
return 0;
}
成对变换:
对一个非负整数n
n为偶数时,n xor 1=n-1;
n为奇数时,n xor 1=n+1;
lowbit(x)是x的二进制表达式中最低位的1所对应的值。(这利用到了位运算的与运算)
int lowbit(int x)
{
return x&-x;
}
现在我们来证明一下 lowbit ( n ) 运算是怎么进行运算的:
我们假设 n > 0 ,设 n 的二进制表示中,第 k 位为 1 ,第 0 至第 k-1 位都为 0 ,现在我们对 n 的二进制进行取反操作,可以得到,~n 的二进制表示中,第 k 位为 0 ,第 0 至第 k-1 位都为 1,然后我们再将 ~n 进行加 1 操作,可以得到一个结果,就是 ~n+1 的第 k+1 位至其最高位都为 n 的二进制表示中相反的数字,然后我们再将 ~n+1 与 n进行与运算,就可以得到我们想要的结果了。又因为 ~n=-1-n ,所以 -n = ~n+1,有:
lowbit( x ) = n & ( ~n + 1 ) = n & ( -n )
上面写的很抽象,我们假设 n = 8 ,8 的二进制为 : 0 0 0 0 1 0 0 0 ,对 8 取反的二进制为 :1 1 1 1 0 1 1 1 ,再对 取反8加一的二进制为 :1 1 1 1 1 0 0 0, 进行与操作之后 : 0 0 0 0 1 0 0 0
就得到了我们的 lowbit ( 8 ) = 8