AcWing 91. 最短Hamilton路径
原题链接
中等
作者:
rushhhhh
,
2021-02-27 15:28:13
,
所有人可见
,
阅读 349
#include<iostream>
#include <cstring>
#include <algorithm>
using namespace std;
/*
状态表示f[i,j]
集合:经过i表示的结点,从0到j的所有路径
属性:最小值
状态计算
把每条路径不重不漏地分类,可以这么分:
枚举每条路径的倒数第二个结点,例如:
0-j可分为倒数第二个结点是
0、1、2、...、n-1
若此结点是k,则
路径分划分为0->k->j,其中k->j = w[k][j]
而0->k则等于f[i-{j}][k]
即所有从0到k,经过结点为i(二进制)除去j的路径
*/
const int N = 21, M = 1<<N;
int n;
int w[N][N], f[M][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++)
// 判断路径是否合法(j结点是否在i表示的集合中)
if(i>>j & 1)
// 枚举倒数第二个结点
for(int k=0; k<n; k++)
// 判断路径是否合法(k结点是否在i表示的集合中)
if(i>>k & 1)
f[i][j] = min(f[i][j], f[i-(1<<j)][k] + w[k][j]);
// 不重不漏地经过每个点恰好一次,所以i是111111
cout << f[(1<<n)-1][n-1];
}