从矩阵左边到矩阵右边,最上最下两行算作相邻,可以
↗
→↘
走。所以记录路径的时候列不用记(+1),输出字典序路径,所以始终从行数最小的行开始找,(从n列开始倒序向前就不会有顺序问题),正序需要判断行数。
#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <algorithm>
#include <vector>
using namespace std;
const int INF = 0x3f3f3f3f;
int a[15][105];
int dp[15][105];
int dis1[][2] = {{1,1},{-1,1},{0,1}};
int dis[][2] = {{-1,1},{0,1},{1,1}};
int dis2[][2] = {{0,1},{1,1},{-1,1}};
int vis[15][105];
int m,n;
int dfs(int x,int y){
int ans = dp[x][y];
int Min = INF;
int mx,my;
if(y == n){
//cout<<x<<y<<endl;
dp[x][y] = a[x][y];
return dp[x][y];
}
for(int i = 0; i < 3; i++){
int nx,ny;
if(x == 1){
nx = x + dis2[i][0];
ny = y + dis2[i][1];
}else if(x == m){
nx = x + dis1[i][0];
ny = y + dis1[i][1];
}else{
nx = x + dis[i][0];
ny = y + dis[i][1];
}
//cout<<nx<<" "<<ny<<endl;
if(nx >= 0 && nx <= m+1 && ny >= 1 && ny <= n){
if(nx == 0)
nx = m;
if(nx == m+1)
nx = 1;
if(dp[nx][ny] == INF)
ans = a[x][y] + dfs(nx,ny);
else
ans = a[x][y] + dp[nx][ny];
}
if(ans < Min){
Min = ans;
mx = nx;
my = ny;
}
}
dp[x][y] = Min;
vis[x][y] = mx;
return dp[x][y];
}
int main(){
while(~scanf("%d%d",&m,&n)){
memset(dp, INF, sizeof dp);
memset(vis, 0, sizeof vis);
for(int i = 1; i <= m; i++)
for(int j = 1; j <= n; j++)
scanf("%d",&a[i][j]);
int Min = INF;
int s;
for(int i = 1; i <= m; i++){
int t = dfs(i,1);
if(t < Min){
s = i;
Min = t;
}
}
int mx = s,my = 1;
printf("%d",s);
while(my != n){
printf(" %d",vis[mx][my]);
mx = vis[mx][my];
my++;
}
printf("\n%d\n",Min);
}
return 0;
}