UVA - 116 Unidirectional TSP
题目
给m行n列矩阵,从第一列任意位置开始向右走,每次走三个方向,走到最后一列最小权值是多少,并打印路径列号。
分析
每次三个决策,即三个方向,直接构建状态转移方程。
注意字典序最小和打印路径的问题。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int N = 1e2 + 10;
int a[N][N];
int dp[N][N]; //从(i,j)到最后一列最小开销
int path[N][N]; //保存路径
int m, n;
void DP()
{
int ans = INF, fir = 0;
for(int j = n; j >= 1; j--){
for(int i = 1; i <= m; i++){
if(j == n){
dp[i][j] = a[i][j];
}else{
int row[3] = {i, i - 1, i + 1}; //三个方向
if(i == 1)
row[1] = m;
if(i == m)
row[2] = 1;
sort(row, row + 3);
dp[i][j] = INF;
for (int k = 0; k < 3; k++){
int v = dp[row[k]][j + 1] + a[i][j];
if(v < dp[i][j]){
dp[i][j] = v;
path[i][j] = row[k];
}
}
}
if(j == 1 && dp[i][j] < ans){ //找第一列最小值
ans = dp[i][j];
fir = i;
}
}
}
printf("%d", fir);
for (int i = path[fir][1], j = 2; j <= n; i = path[i][j], j++)
printf(" %d", i);
printf("\n%d\n", ans);
}
int main()
{
while(cin >> m >> n){
for(int i = 1; i <= m; i++){
for (int j = 1; j <= n; j++){
cin >> a[i][j];
}
}
DP();
}
return 0;
}