AcWing 91. 最短Hamilton路径

思路

一个典型的状态压缩问题,状态压缩核心的思想就是把一个要用集合表示的状态用一个二进制的数来表示,
这里要求所有路的最短路径,状态怎么表示呢?

首先如果一条路径的起点和终点确定了,经过了那几个点也确定了,权值知道,那么就可以表示一条路径了,所以我们用f[i][j]表示状态,其中i表示了所有点的状态,也就是是否经过了,j表示终点,因为起点都是0,所以我们只要记录终点就可以了。

状态压缩:如果要表示一群点的状态的话,首相想到的数据结构是集合,但是这里可以用状态压缩,因为一个点的状态只有两个,经过和没经过,所有每一个点的状态都可以用一个二进制位来表示那么一共最多有20个点,那么我们就可以用一个20位的二进制数来表示所有点的状态了。

状态转移:f[i][j]怎么转移呢?,一个点肯定是由前一个点过来的,所以f[i][j]=min(f[i][j],f[s][k]),其中k为上一个终点,s为上一个终点的状态,当然是有条件的,s中在j位上一定是0,在k上一定是1。

步骤:
1.存下所有的权w[i][j];
(其中初始化 f[1][0]=0,因为终点为0时距离为0,而且状态为1)
2.枚举所有的状态(循环一)
3.枚举所有的终点(循环二)
4.枚举所有终点的前一个点(循环三)

代码

#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N=20;
int n;
int f[1<<N][N];
int w[N][N];
int main(){
    cin >> n;
    for(int i=0;i<n;i++)
    {
      for(int j=0;j<n;j++){
          cin >> w[i][j];
      }
    }
    memset(f,0x3f,sizeof(f));
    f[1][0]=0;
    for(int i=0;i<1<<n;i++){
        for(int j=0;j<n;j++){
            if(i>>j & 1){
                for(int k=0;k<n;k++){
                    if(i >> k&1)
                    {
                        f[i][j]=min(f[i][j],f[i-(1<<j)][k]+w[k][j]);
                    }
                }
            }
        }
    }
    cout << f[(1<<n)-1][n-1];
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值