题目链接:
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=52
题目意思:
给你一个矩阵,让你求从第一列到最后一列的所有路径中值最小的那个,其中可以向上一行或当行或下一行走,其中最后一行和第一行可以看成相邻的。如果有多条值相同的路径,要求保证按字典顺序最小的输出路径。
解题思路:
从右向左依次动态规划,并保存路径。这样可以保证最后路径输出的是字典序最小的。
详见代码:
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<stack>
#include<queue>
#define eps 1e-6
#define INF (1<<20)
#define PI acos(-1.0)
using namespace std;
int save[15][120];
int dp[120][15],path[120][15],m,n; //dp[i][j]表示从最后一列到第i列第j行为止最小的值
//相应的path[i][j]表示到达第i列第j行的后一列的行数
int main()
{
while(scanf("%d%d",&m,&n)!=EOF)
{
memset(path,-1,sizeof(path));
memset(dp,0,sizeof(dp));
for(int i=1;i<=m;i++)
{
int j;
for(j=1;j<n;j++)
scanf("%d",&save[i][j]);
scanf("%d",&save[i][j]);
dp[j][i]=save[i][j]; //初始化
}
for(int i=n-1;i>=1;i--)
{ //先考虑第一行的情况
dp[i][1]=dp[i+1][1]; //注意比较的顺序
path[i][1]=1;
if(m>1&&dp[i+1][2]<dp[i][1]) //注意考虑只有一行的情况,m>1不能省略
{
dp[i][1]=dp[i+1][2];
path[i][1]=2;
}
if(dp[i+1][m]<dp[i][1])
{
dp[i][1]=dp[i+1][m];
path[i][1]=m;
}
dp[i][1]+=save[1][i];
for(int j=2;j<m;j++) //考虑第二行到倒数第二行的情况,此时情况都一样,可以统一处理
{
dp[i][j]=dp[i+1][j-1];
path[i][j]=j-1;
if(dp[i+1][j]<dp[i][j])
{
dp[i][j]=dp[i+1][j];
path[i][j]=j;
}
if(dp[i+1][j+1]<dp[i][j])
{
dp[i][j]=dp[i+1][j+1];
path[i][j]=j+1;
}
dp[i][j]+=save[j][i];
}
dp[i][m]=dp[i+1][1]; //考虑最后一行的情况
path[i][m]=1;
if(m>1&&dp[i+1][m-1]<dp[i][m]) //注意考虑只有一行的情况,m>1不能省略
{
dp[i][m]=dp[i+1][m-1];
path[i][m]=m-1;
}
if(dp[i+1][m]<dp[i][m])
{
dp[i][m]=dp[i+1][m];
path[i][m]=m;
}
dp[i][m]+=save[m][i];
}
int sum=dp[1][1],begin=1;
for(int i=2;i<=m;i++) //统计最少的那条路径
{
if(dp[1][i]<sum)
{
sum=dp[1][i];
begin=i;
}
}
printf("%d",begin);
int temp=1;
while(path[temp][begin]!=-1) //输出路径
{
printf(" %d",path[temp][begin]);
begin=path[temp][begin];
temp++;
}
printf("\n%d\n",sum); //输出最小的和
}
return 0;
}
本文介绍了一种使用动态规划解决从矩阵第一列到最后一列路径中最小值的问题,并确保输出字典序最小的路径。通过从右向左依次更新路径值和路径选择,最终确定最小路径和其和。
1113

被折叠的 条评论
为什么被折叠?



