原题:

状态表示:f[ i ][ j ]
集合:从 0 走到 j 的最短路径, i 表示路径上所有经过的点(二进制表示,十进制储存)
如 :经过的点是 0 1 3 5 则 i 的二进制表示为 110101
属性:最小值
状态转移方程:f[i][j] = min(f[i][j], f[i - (1 << j)][k] + w[k][j]);
描述:f[i - (1 << j)][k] 表示从 0 走到 j 的经过的点除去点 j
思想 :
① 0 -> 3 -> 5 -> 1 -> 7 -> n - 1
② 0 -> 1 -> 3 -> 5 -> 7 -> n - 1
两种到 7 的路径对其后的计算效果是一样的, 所以只用计算从 0 到 7 的路径的和,再加上w[7][n - 1]。
#include <bits/stdc++.h>
using namespace std;
const int N = 20, M = 1 << N;
int f[M][N], w[N][N];
int 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 = 1; i < 1 << n; i ++ )
for(int j = 1; 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] << endl;
}
本文介绍了一种使用动态规划解决带有限定点集的最短路径问题的方法。通过二进制位标记已访问节点,并利用状态转移方程优化路径选择,实现高效计算。
1244

被折叠的 条评论
为什么被折叠?



