XP学长觉得矩阵很美,虽然他也不知道美在哪里,因此,他决定挖掘一下矩阵的美。现在给定一个m行n列的矩阵,从左上角开始每次只能向右或者向下移动,最后到达右下角的位置,将路径上的所有数字累加起来作为这条路径的路径和。XP学长决定编写一个程序来求所有路径和中的最小路径和。例如,下面矩阵中的路径1-3-1-0-6-1-0是所有路径中路径和最小的,返回结果是12。
1 3 5 9
8 1 3 4
5 0 6 1
8 8 4 0
输入
输入包含多组测试用例,第一行输入一个T表示测试数据组数,(1<=T<=15)
接下来有T组数据,每组先输入两个整数M,N接下来输入M*N的矩阵(1<=N,M<=1000),且最终结果在int范围内。
输出
输出路径和的最小值。
样例输入 Copy
1 4 4 1 3 5 9 8 1 3 4 5 0 6 1 8 8 4 0
样例输出 Copy
12
仅仅是我的思路,并非最优解,因为跑出来要了500多ms,时间太长了,但是我觉得思路挺简单的 。
讲一下思路:动态规划问题最重要的就是先要定义好dp数组,什么叫定义好呢,就是你自己要清楚dp的含义,就是他可以表示的意义,这个题dp[i][j]就是表示当遍历到数组a[i][j]时的最短路径是多少。第二就是要确定好转移方程,就是要建立好dp与dp之间的联系,这个题就是说了“每次只能向右或者向下移动“,此时在结合我们的dp数组,向右就是i+1嘛,向下就是j+1嘛。所以这个题我们是由我们定义的dp数组的含义可以知道初始值if(i==1)dp[i][j]=dp[i][j-1]+a[i][j],if(j==1)dp[i][j]=dp[i-1][j]+a[i][j];可以看出来dp[i][j]与dp[i-1][j]和dp[i][j-1]有关,所以我们此时就需要从左往右遍历和从上往下遍历就行了
#include<bits/stdc++.h>
using namespace std;
int a[1005][1005];
int dp[1005][1005];
int main(){
int T;
while(cin>>T){
while(T--){
memset(a,0,sizeof(a));
memset(dp,0,sizeof(dp));
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin>>a[i][j];
if(j==1)dp[i][j]=dp[i-1][j]+a[i][j];//仔细想想是不是第一列只能来自它的上方,因为它没有左边
if(i==1)dp[i][j]=dp[i][j-1]+a[i][j];//这个也同理只能来自左边
}
}
for(int i=2;i<=n;i++){
for(int j=2;j<=m;j++){
dp[i][j]=min(dp[i][j-1],dp[i-1][j])+a[i][j];
}
}
cout<<dp[n][m]<<endl;
/* for(int i=1;i<=n;i++)//这个for循环是用来验证答案是否正确
for(int j=1;j<=m;j++){
cout<<dp[j][j]<<" ";
if(j==m)cout<<endl;
}*/
}
}
return 0;
}