HNUCM XP的矩阵(附动态规划思路)

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;
}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

H-rosy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值