题解:
单向TSP,通过上一步的状态推出下一步的状态,和数字三角形的想法是一样的
紫书上解释挺详细了,这里不用递归来做的话,由前往后推是不行的,因为要字典序最小,如果从前往后推的话是找不出来的(不信可以试一下)
以后弄dp都从后往前推稳定一点
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
int n,m;
int block[15][110];
int dp[15][110],fro[15][110];
int re_num(int pos, int lr) {
pos += lr;
if(pos <= 0) return n;
if(pos > n) return 1;
return pos;
}
int main()
{
//freopen("in.txt","r",stdin);
while(scanf("%d%d",&n,&m) == 2) {
memset(fro,0,sizeof(fro));
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= m; j++) {
scanf("%d",&block[i][j]);
}
}
memset(dp,inf,sizeof(dp));
for(int i = 1; i <= n; i++) dp[i][m] = block[i][m];
for(int j = m-1; j >= 1; j--) { //每例
for(int i = 1; i <= n; i++) { //每行
for(int k = -1; k <= 1; k++) {
int num = re_num(i,k);
if(dp[i][j] > dp[num][j+1]+block[i][j] || (dp[i][j]==dp[num][j+1]+block[i][j]&&fro[i][j]>num)) {
dp[i][j] = dp[num][j+1]+block[i][j];
fro[i][j] = num;
}
}
}
}
int r,minn = inf;
for(int i = 1; i <= n; i++)
if(minn > dp[i][1]) {
r = i;
minn = dp[i][1];
}
int l = 1;
for(int i = r; i != 0; i = fro[i][l++]) {
if(l != 1) printf(" ");
printf("%d",i);
}
printf("\n%d\n",minn);
}
return 0;
}