UVa 116 - Unidirectional TSP (dp)
题目链接:https://onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&category=0&problem=52&mosmsg=Submission+received+with+ID+26597725
普通最短路径 \(dp\),但因为要输出字典序最小的方案,所以要逆推
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 110;
const int INF = (1 << 30) + 1;
int n, m;
int a[maxn][maxn];
int dp[maxn][maxn], pre[maxn][maxn];
ll read(){ ll s = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); } while(ch >= '0' && ch <= '9'){ s = s * 10 + ch - '0'; ch = getchar(); } return s * f; }
int main(){
while(scanf("%d%d", &n, &m) == 2 && m){
for(int i = 1 ; i <= n ; ++i){
for(int j = 1 ; j <= m ; ++j){
scanf("%d", &a[i][j]);
}
}
int pos, ans = (1 << 30) + 10;
for(int j = m ; j >= 1 ; --j){
for(int i = 1 ; i <= n ; ++i){
if(j == m) dp[i][j] = a[i][j];
else{
int row[3] = {i-1, i, i+1};
if(i == 1) row[0] = n;
if(i == n) row[2] = 1;
sort(row, row + 3);
dp[i][j] = INF;
for(int k = 0 ; k <= 2 ; ++k){
int val = dp[row[k]][j+1] + a[i][j];
if(val < dp[i][j]){
dp[i][j] = val; pre[i][j] = row[k];
}
}
}
if(j == 1 && dp[i][j] < ans){
ans = dp[i][j]; pos = i;
}
}
}
printf("%d", pos);
for(int i = 1 ; i <= m - 1 ; ++i){
printf(" ");
printf("%d", pre[pos][i]);
pos = pre[pos][i];
} printf("\n");
printf("%d\n", ans);
}
return 0;
}