75.穿越矩阵 (15分)
C时间限制:3000 毫秒 | C内存限制:3000 Kb
题目内容:
现在有一个 m * n 的整数矩阵,请你编写一个程序计算出一条从左到右穿过矩阵的路径,并使此路径的费用最小。路径从矩阵
的左侧的第一列的任意单元格开始,逐步穿过矩阵到达最右侧的一列的任意单元格。每一步是指从某单元格进入它一列的相邻单元
格(如下图,可以是横向或斜向)。矩阵的第一行和最后一行实际是相邻的,你可以想象矩阵是包裹在一个横放的圆柱体外面(这点很重要)。
路径的花费是指这条路径所穿越的所有单元格中的数字之和。
输入描述
输入包括一系列矩阵描述。每个矩阵描述的第一行是 m 和 n,即矩阵的行数和列数;之后的 m 行,每行包括 n 个以空格分开的
整数,则是当前矩阵的值,注意矩阵的值未必是正数。
矩阵的行数 m 和列数 n 的范围是:1 <=m<=10、 1<=n<=100;所有路径的费用值都可以用 30bit 的整数表示。
输出描述
针对每一个矩阵,找出费用最小的路径,并将其输出。每个矩阵的输出包括两行,第一行是路径本身,即输出每一步所在的行,第
二行则是该路径的费用。
如果对于同一个矩阵有多条不同的费用最小路径,则输出左端行号较小的一条。
输入样例
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
输出样例
1 2 1 5 4 5
11
#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
const int maxn =101;
int dp[11][maxn],a[11][maxn],num[maxn];
const int INF = 0x3f3f3f3f;
int main(){
int n,m;
cin>>n>>m;
memset(dp,INF,sizeof(dp));
memset(num,0,sizeof(num));
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
scanf("%d",&a[i][j]);
}
}
for(int i=0;i<n;i++){
dp[i][m-1] = a[i][m-1];
}
for(int i =m-2;i>=0;i--){
for(int j=0;j<n;j++){
dp[j][i] = a[j][i];
if(j>0&&j<n-1){
dp[j][i] +=min(min(dp[j][i+1],dp[j+1][i+1]),dp[j-1][i+1]);
}
else if(j==0){
dp[j][i] +=min(min(dp[j][i+1],dp[j+1][i+1]),dp[n-1][i+1]);
}
else if(j==n-1)
dp[j][i]+=min(min(dp[j][i+1],dp[j-1][i+1]),dp[0][i+1]);
}
}
int min = dp[0][0],mm=0;
for(int i = 1;i<n;i++){
if(dp[i][0]<min){
min = dp[i][0];
mm = i;
}
}
num[0] = mm;
for(int i=1;i<m;i++){
int flag = 0;
for(int j=0;j<n;j++){
if(mm==0&&j!=0&&j!=1&&j!=n-1)
continue;
if(mm==n-1&&j!=0&&j!=n-1&&j!=n-2)
continue;
if(mm>0&&mm<n-1&&j!=mm&&j!=mm-1&&j!=mm+1)
continue;
if(dp[mm][i-1] - a[mm][i-1] == dp[j][i]){
mm = j;
num[i] = mm;
flag = 1;
}
if(flag)
break;
}
}
for(int i=0;i<m;i++){
if(i!=m-1)
cout<<num[i]+1<<" ";
else
cout<<num[i]+1<<endl;
}
cout<<min<<endl;
return 0;
}