单向TSP。
从后往前依次dp左, 左上, 左下。然后记录当前对应的最小字典序。
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int INF = 1 << 27;
const int maxn = 123;
int ans, first;
int a[maxn][maxn], d[maxn][maxn], Next[maxn][maxn];
int main() {
int m, n;
while(cin >> m >> n) {
memset(a, 0, sizeof(a));
memset(d, 0, sizeof(d));
memset(Next, 0, sizeof(Next));
ans = INF;
for(int i = 0; i < m; i++) {
for(int j = 0; j < n; j++) {
cin >> a[i][j];
}
}
for(int j = n - 1; j >= 0; j--) {
for(int i = 0; i < m; i++) {
if(j == n - 1) {
d[i][j] = a[i][j];
} else {
int row[] = {i, i - 1, i + 1};
if(i == 0) row[1] = m - 1;
if(i == m - 1) row[2] = 0;
sort(row, row + 3);
d[i][j] = INF;
for(int k = 0; k < 3; k++) {
int t = d[row[k]][j + 1] + a[i][j];
if(t < d[i][j]) {
d[i][j] = t;
Next[i][j] = row[k];
}
}
}
if(j == 0) {
if(d[i][j] < ans) {
ans = d[i][j];
first = i;
}
}
}
}
// cout << first << endl;
for(int j = 0, i = first; j < n; i = Next[i][j], j++) {
if(j) cout << " ";
cout << i + 1;
}
cout << endl << ans << endl;
}
return 0;
}