题目大意:
给一个m行n列(m≤10,n≤100)的整数矩阵,从第一列任何一个位置出发每次往右、右上、右下走一格,最终到达最后一列。要求经过的整数之和最小。整个矩阵是环形的,即第一行的上一行是最后一行,最后一行的下一行是第一行。输出路径上每列的行号。多解时输出字典序最小的。
输入有若干组数据:
每组的第1行:m和n,分别为行数和列数。
每组的第2~m+1行:每行n个数,用空格分开,代表整数矩阵。
输出:
每组有两行,第一行是每列的行号,第二行是路径的经过的整数之和。
解题思路:
设dp[i][j]表示从i,j格子出发到最后一列的最小开销,并记录后一列的行号
调试记录:
memset付初始值得时候有问题,赋的值不够大导致wa,将INF改为0x3f3f3f即可
下面看代码
1#include<bits/stdc++.h>
2using namespace std;
3int mat[40][405],dp[40][405],n,m,path[50][505],cost,INF;
4int main(){
5 INF=0x3f3f3f3f;
6 while (scanf("%d%d",&n,&m)==2){
7 for (int i=1;i<=n;i++)
8 for (int j=1;j<=m;j++)
9 scanf("%d",&mat[i][j]);
10 memset(dp,INF,sizeof(dp));
11 for (int i=1;i<=n;i++) dp[i][m]=mat[i][m];
12 for (int j=m;j>1;j--){//逆推转移
13 for (int i=1;i<=n;i++){
14 int row[3];//可以走过来的三方向
15 row[0]=i-1;row[1]=i;row[2]=i+1;
16 if (i==1) row[0]=n;
17 if (i==n) row[2]=1;
18 sort(row,row+3);//排序保证字典序最小
19 for (int x=0;x<3;x++){
20 int tmp=dp[i][j]+mat[row[x]][j-1];
21 if (tmp<dp[row[x]][j-1]){
22 dp[row[x]][j-1]=tmp;
23 path[row[x]][j-1]=i;
24 }
25
26 }
27 }
28 }
29 int cost=INF,r;
30 for (int i=1;i<=n;i++)
31 if (cost>dp[i][1])
32 r=i,cost=dp[i][1];
33 printf("%d",r);
34 for(int i = path[r][1],j=1;j<m;j++,i = path[i][j])
35 printf(" %d", i);
36 printf("\n%d\n",cost);
37 }
38 return 0;
39}