题意:
给定整数矩阵,从第一列的任何一个位置出发,每次可以向右、右上、右下走一个格,将最后一行和第一行看成是邻接的,最终到达最后一列,路径长度为所经过格中的整数之和,求最小路径,答案不唯一,输出字典序最小的路径。
分析:
数组dp[i][j]记录从第i行第j列出发,到达最后一列的最小路径长度
- 每个阶段都有三种决策,向右/右上/右下【注意最后一行和第一行的情况
- 字典序最小,每次都先选择字典序较小的决策
- 打印路径,记录下一个位置
代码:
#include<iostream>
#include<cmath>
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn = 100, INF=0x3fffffff;
int c[maxn][maxn], dp[maxn][maxn], s[maxn][maxn];
int main (void)
{
int m ,n;
while(cin>>n>>m){//n行m列
for(int i = 0; i < n; i++){
for(int j = 0; j < m; j++){
cin>>c[i][j];
dp[i][j] = INF;
}
}
for(int i = m -1; i >= 0; i--){//j行i列
for(int j = 0; j < n; j++){
if(i == m - 1) {dp[j][i] = c[j][i];continue;}
int r[3]={j, j + 1, j - 1};
if(j + 1==n) r[1] = 0;
if(j - 1==-1) r[2] = n-1;
sort(r, r+3);
for(int k = 0; k < 3; k++){
int d = dp[r[k]][i+1] + c[j][i];
if(d<dp[j][i]){
dp[j][i] = d ;
s[j][i] = r[k];
}
}
}
}
int ans = INF, t = 0;
for(int i = 0 ; i < n; i++){
if(dp[i][0]<ans){
ans = dp[i][0];
t = i;
}
}
cout<<t+1;
for(int i = 0; i < m - 1; i++){
t = s[t][i];
cout<<' '<<t+1;
}
cout<<endl<<ans<<endl;
}
}