最短Hamilton路径(二进制状态压缩DP)

最短hamilton路径问题已经被证明是一个NPhard问题,求解最短路径复杂,所以要对问题进行状态压缩,我们用f[i][j]来表示以节点j为结尾时所经过的节点。表示方式为将第一维的i以二进制来进行表示,每一位的1或0表示该点是否被走过,所以我们第一维有2^{n}种状态。我们以8个节点为例,第一个节点为0,最后一个节点为7,我们所需要求的最终状态即为f[255][7]

将255转化为二进制表示即为011111111,可以发现该状态为从0到7所有节点都被遍历且以7为结尾,说明我们遍历了图中所有的节点一次并且来到了终点7。

ACcode

// #pragma GCC optimize (2)
// #pragma G++ optimize (2)
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
#include <unordered_map>
#include <map>
#include <bitset>
#include <set>
#define endl '\n'
#define int long long
#define lowbit(x) x &(-x)
#define rep(i, a, n) for (int i = a; i <= n; i++)
const double esp = 1e-5;
using namespace std;
void TLE() { ios::sync_with_stdio(false), cin.tie(0), cout.tie(0); }
const int N=20,M=1<<20;
int f[M][N],weight[N][N];
int n;
void solve()
{
    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;//遍历过1号节点且以0为终点的路径个数为1
    for(int i=0;i<1<<n;i++)//遍历所有pow(2,n)个状态
        for(int j=0;j<n;j++)
            if(i>>j&1)//判断该状态是否合法经历过j并且以j为结尾才为合法状态,只需判断i的二进制表示第j个位置是否为1
                for(int k=0;k<n;k++)
                {
                    if(i-(1<<j)>>k&1)//判断该更新是否合法
                    {
                       f[i][j]=min(f[i][j],f[i-(1<<j)][k]+weight[k][j]);
                    }
                }
    cout<<f[(1<<n)-1][n-1]<<endl;//输出便利过所有节点并且以n-1为结尾的最路径
}
signed main()
{
    TLE();
    int T;T = 1;
    // int T;cin>>T;
    while (T--)
        solve();
    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值