二进制状态压缩解决哈密顿最短路径问题
程序员文章站
2022-05-18 10:25:08
...
右边为第0位,左边为第n-1位
1. 取出整数n在二进制表示下的第k位 (n>>k)&1
1001 0100 取出第4位 0000 1001&0000 0001-> 0000 0001
2. 取出整数n在二进制表示下的第0~k-1位(后k位) n&((1<<k)-1)
1001 0100 取出后5位 0010 0000-1=0001 1111
3.把整数n在二进制表示下的第k位取反
n xor (1<<k) 异或运算
4.把整数n在二进制表示下的第k位赋值1
n|(1<<k)
5.把整数n在二进制表示下的第k位赋值1
n&(~(1<<k)) ~为取反操作
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int weight[20][20];//存边
int f[1<<20][20];
int main()
{
int n;//n个顶点,编号为0-n-1
cin>>n;
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
cin>>weight[i][j];
}
}
memset(f,0x3f,sizeof(f));//初始化为无穷大
f[1][0]=0;//i=1,表示目前只经过了i点,j=0,表示目前在0号节点
for(int i=1;i<1<<n;i++)//枚举所有的状态
{
for(int j=0;j<n;j++)//接下来是两层for循环,第一层枚举哪个顶点已经经过了,第二层循环
{
if(i>>j&1)//i的第j位是1,刚刚经过j
{
for(int k=0;k<n;k++)//枚举是哪个顶点到达j的
{
if((i^1<<j)>>k&1)//i的第j位先弄为0,然后看哪个位是1,即有可能从该顶点到达顶点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,且前n-1个顶点都经过了
return 0;
}
推荐阅读