建矩阵的时候,不建议走传统的 [行,列] 的方式。为了递推的方便,最好 [列,行] 这样建。我是按照传统的方法做的,中途遇到好几次行、列混淆,dp的大小也声明反了(幸好得的是RE,如果是WA可能又要浪费很多时间)。
关于打印路径:我自己按照UVa #1599 Ideal Path(例题6-20)的方法做(Rujia强烈推荐那道题的原因),虽然有一点麻烦,但是AC了。按照书中这道题给的方法做(用一个next数组)却得了WA。以后再查。
有阶段的动态规划用递推非常直观。其实之前的UVa #1347 Tour (例题9-4)就有一点“阶段”的味道。
Run Time: 0.109s
#define UVa "LT9-4.116.cpp" //Unidirectional TSP
char fileIn[30] = UVa, fileOut[30] = UVa;
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
//Global Variables. Reset upon Each Case!
const int maxm = 10 + 5, maxn = 100 + 5;
int matrix[maxm][maxn];
int dp[maxn + 1][maxm + 1];
/
int main() {
int m, n; //m: row dimension. n: col dimension.
while(scanf("%d%d", &m, &n) != EOF) {
for(int i = 0; i < m; i ++) for(int j = 0; j < n; j ++) scanf("%d", &matrix[i][j]); //matrix index starts from 1.
for(int i = 0; i < m; i ++) dp[n-1][i] = matrix[i][n-1];
for(int i = n-2; i >= 0; i --) {
for(int j = 0; j < m; j ++) {
int d1 = (j-1+m)%m;
int d2 = (j+1)%m;
dp[i][j] = dp[i+1][j];
dp[i][j] = min(dp[i][j], dp[i+1][d1]);
dp[i][j] = min(dp[i][j], dp[i+1][d2]);
dp[i][j] += matrix[j][i];
}
}
int ans = dp[0][0], ansm = 0;
for(int i = 0; i < m; i ++) {
if(dp[0][i] < ans) {
ans = dp[0][i];
ansm = i;
}
}
int prevm = ansm;
vector<int> v;
v.push_back(ansm);
for(int i = 0; i < n-1; i ++) {
int d[3];
d[0] = prevm;
d[1] = (prevm-1+m)%m;
d[2] = (prevm+1)%m;
int prevans = dp[i][prevm];
int curm = -1;
for(int j = 0; j < 3; j ++) {
if(dp[i+1][d[j]] == prevans - matrix[prevm][i] && (curm == -1 || d[j] <= curm)) {
curm = d[j];
}
}
prevm = curm;
v.push_back(curm);
}
for(int i = 0; i < v.size(); i ++) printf("%d%c", v[i]+1, (i!=v.size()-1)?' ':'\n');
printf("%d\n", ans);
}
return 0;
}