d[i][j]存放往右,右上,右下的最优决策,next[i][j]存放最优且字典序最小的行数,然后从最后一列逆退回来。
d[i][j]代表目前的位置是i,j,且存放的是从该列到最后一列的最小整数和。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int INF=10000;
int main()
{
int m,n;
int G[10][100];
int d[10][100];
int next[10][100];
while(scanf("%d%d",&m,&n)!=EOF)
{
int ans=INF;
int first=0;
for(int i=0;i<m;i++)
for(int j=0;j<n;j++)
d[i][j]=INF;
for(int i=0;i<m;i++)
for(int j=0;j<n;j++)
scanf("%d",&G[i][j]);
for(int j=n-1;j>=0;j--)
{
for(int i=0;i<m;i++)
{
if(j==n-1) d[i][j]=G[i][j];
else{
int row[3]={i,i-1,i+1};
if(i==0) row[1]=m-1;
if(i==m-1) row[2]=0;
sort(row,row+3);
for(int k=0;k<3;k++){
int v=d[row[k]][j+1]+G[i][j];
if(v<d[i][j]) {d[i][j]=v;next[i][j]=row[k];}
}
}
if(j==0&&d[i][j]<ans) {ans=d[i][j];first=i;}
}
}
printf("%d",first+1);
for(int i=next[first][0],j=1;j<n;i=next[i][j],j++)
printf(" %d",i+1);
printf("\n%d\n",ans);
}
return 0;
}