【AC代码分享】
本题是简单的动态规划问题,但是打印出字典序最小的路径笔者费了一番周折!笔者特别处理了遇到多解时要输出最小字典序的问题。详见代码如下:
/*
d(i,j)表示从位置(i,j)出发的最短路径
d(i,j)=min{d(i-1,j+1),d(i,j+1),d(i+1,j+1)}
*/
#include<bits/stdc++.h>
using namespace std;
const int maxn=1005;
int m,n;
int a[maxn][maxn];
int d[maxn][maxn];
int path_next[maxn][maxn];
int main()
{
while(cin>>m>>n){
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++){
cin>>a[i][j];
}
}
for(int i=1;i<=m;i++){
d[i][n]=a[i][n];
}
for(int j=n-1;j>=1;j--){
for(int i=1;i<=m;i++){
int r1=(i==1?m:i-1);
int r2=i;
int r3=(i==m?1:i+1);
int v1=d[r1][j+1];
int v2=d[r2][j+1];
int v3=d[r3][j+1];
//因为要打印出最短路径,下面分了几种情况全面讨论
if(v1==v2 && v1==v3){
path_next[i][j]=min(r1,min(r2,r3));//第j列i行下一个是第j+1列的r2,r3中的较小值,下类似
d[i][j]=a[i][j]+v1;
}
else if(v3<=v2 && v3<=v1){
path_next[i][j]=r3;
if(v3==v2){
path_next[i][j]=min(r2,r3);
}
if(v3==v1){
path_next[i][j]=min(r3,r1);
}
d[i][j]=a[i][j]+v3;
}
else if(v2<=v1 && v2<=v3){
path_next[i][j]=r2;
if(v2==v1){
path_next[i][j]=min(r1,r2);
}
if(v2==v3){
path_next[i][j]=min(r2,r3);
}
d[i][j]=a[i][j]+v2;
}
else if(v1<=v2 && v1<=v3){
path_next[i][j]=r1;
if(v1==v2){
path_next[i][j]=min(r1,r2);
}
if(v1==v3){
path_next[i][j]=min(r1,r3);
}
d[i][j]=a[i][j]+v1;
}
}
}
int ans=d[1][1];
int mark=1;
//找到最小字典序的解对应的第一列的行
for(int i=1;i<=m;i++){
if(ans>d[i][1]){
ans=d[i][1];
mark=i;
}
}
cout<<mark;
int cnt=0;
while(++cnt<n){
cout<<" "<<path_next[mark][cnt];//注意末尾不要多输出一个空格,否则Presentation Error
mark=path_next[mark][cnt];
}
cout<<endl;
cout<<ans<<endl;
}
return 0;
}