给定一个m*n的矩阵,请写一个程序计算一条从左到右走过矩阵且权和最小的路径。一条路径可以从第1列的任意位置出发,到达第n列的任意位置。每一步只能从第i列走到第i+1列的同一行或者相邻行(第一行和最后一行看作是相邻的)。
1 | 2 | 3 | 4 | 5 |
6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 |
21 | 22 | 23 | 24 | 25 |
例如1 -> 2 -> 23 -> 24 ->25就是一条路径。
路径的权和为所有经过的n个方格中整数的和。
Input
输入数据包含一个矩阵。
输入数据的第一行为两个数,m和n,分别表示矩阵的行数和列数。(0<m*n<=10000)
接下来m*n个整数按照行优先的顺序依次排列。
Output
输出数据包含两行。
第一行给出一个整数,为最小路径的权值。
第二行给出最小路径上从左到右依次经过的行号,有多个最小路径时输出字典序最小的一条。
Sample Input
5 6 3 4 1 2 8 6 6 1 8 2 7 4 5 9 3 9 9 5 8 4 1 3 2 6 3 7 2 1 2 3
Sample Output
11 1 2 1 5 4 5
#include <stdio.h> #include <string.h> #include <algorithm> using namespace std; int a[10005][10005]; int path[10005][10005]; const int inf = 99999999; int main() { int n,m,i,j,ans,to,v,k,p; while(~scanf("%d%d",&n,&m)) { for(i = 0; i<n; i++) for(j = 0; j<m; j++) scanf("%d",&a[i][j]); for(i = m-2; i>=0; i--)//从第m-2列开始,枚举所有状况 { for(j = 0; j<n; j++) { int minn = inf,id = inf; for(to = -1; to<=1; to++) { v = a[(j+to+n)%n][i+1]; p = (j+to+n)%n; if(minn>v || (minn == v && p<id))//找出最小路径,相同则找字典序小的 { minn = v; id = p; } } a[j][i]+=minn; path[j][i] = id; } } ans = inf; for(i = 0; i<n; i++) { if(ans>a[i][0]) { ans = a[i][0]; k = i; } } printf("%d\n%d",ans,k+1); for(i = 0; i<m-1; i++) { printf(" %d",path[k][i]+1); k = path[k][i]; } printf("\n"); } return 0; }