最短Hamilton路径

题目来源:算法竞赛进阶指南

题目标签:状态压缩DP,二进制状态枚举

题目链接:https://www.acwing.com/problem/content/93/

思路:1. f [ state ][ j ] : 表示在state状态下,最后一个被选中的点是 j 点。

   2.枚举所有可能出现的状态和最后一个点的值。

   3.枚举当前点的前一个点,当前状态可以由前一个点转移过来

      *tips:题目要求终点一定是n - 1, 如果没有要求需要对终点也进行枚举取最小

代码:

#include <bits/stdc++.h>
using namespace std;

const int N = 20, M = 1 << 20;

int n;
int f[M][N], weight[N][N];

int main()
{
    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;
    
    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 - (1 << j) >> k & 1)
                    //保证点k存在于当前状态减去当前点后的状态(保证k点已经被经过,并且和当前点不是同一个点)
                        f[i][j] = min(f[i][j], f[i - (1 << j)][k] + weight[k][j]);
                        //当前状态是由K转移到当前点的最小代价
                        
    cout << f[(1 << n) - 1][n - 1] << endl;
    //最后状态:所有点全部被选中,已经到达最后一个点
            
    return 0;
}

 

上一篇:0103 最短Hamilton路径(状压DP)


下一篇:linux 学习第十四天(Apache安装、基于ip、基于域名、基于端口配置)