二进制状态压缩解决哈密顿最短路径问题

右边为第0位,左边为第n-1位

 1. 取出整数n在二进制表示下的第k位	(n>>k)&1
 1001 0100  取出第40000 1001&0000 0001-> 0000 0001
 2. 取出整数n在二进制表示下的第0~k-1位(后k位)  n&((1<<k)-1)
 1001 0100 取出后50010 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))  ~为取反操作

二进制状态压缩解决哈密顿最短路径问题_第1张图片

#include 
#include 
#include 
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;
}

你可能感兴趣的:(基本算法,算法)