寻宝路线

7-9 寻宝路线 (30 分)

在一个m行n列方格矩阵中,每一个方格内摆放着价值不等的宝贝(价值可正可负),让小明感到好奇的是,从左上角到达右下角的所有可能路线中,能捡到宝贝的价值总和最大是多少?而且这种达到最大值的路线 又有多少条?【注意:只能从一个格子向下或向右走到相邻格子,并且走到的格子宝贝一定会被捡起。】

输入格式:

第一行为整数m,n(均不大于100),下一行开始会有一个m行n列的整数方阵,对应方格矩阵中的宝贝价值(这些值的绝对值都不超过500)。

输出格式:

单独一行输出2个整数,分别为能捡到宝贝价值总和的最大值和达到最大值的路线数量,2个整数间隔一个空格。

输入样例:

在这里给出一组输入。例如:

4  5
2  -1  6  -2  9
-3  2  5  -5  1
5   8  3  -2  4
5   2  8  -4  7

输出样例:

对应的输出为:

26 3

 

思路:求最大值比较容易,但有个需注意的点,就是我的数组下标1开始,所以边界一定要特殊处理,因为dp这个数组在下标为0是本身是0,会影响有负数的格子,然后就是路线的输出,可以根据最大值和最大值所在的位置来回溯求路线

 

#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;

int dp[105][105]={0};
int a[105][105];
int ans = 0;
int dir[2][2]={0,-1,-1,0};
int n,m;


void dfs(int sum,int row,int col)
{
    if(sum == a[1][1])
	{
		ans++;
		return ;
	}	
	else
	{
		for(int k = 0;k < 2;++k)
		{
			int rr = row+dir[k][0];
			int cc = col+dir[k][1];
			if(rr < 1 || cc < 1 || rr > n || cc > m) continue;
			if(sum-a[row][col] == dp[rr][cc])
			{
				dfs(sum-a[row][col],rr,cc);
			}
		}
	}
}

int main()
{

    
	scanf("%d%d",&n,&m); 
	for(int i = 1;i <= n;++i)
	{
		for(int j = 1;j <= m;++j)
		    scanf("%d",&a[i][j]);
	}
	
	
	for(int i = 1;i <= n;++i)
	{
		for(int j = 1;j <= m;++j)
		{
			//因为有正负 
			if(j == 1)
			   dp[i][j] = dp[i-1][j]+a[i][j];
			else if(i == 1)
			   dp[i][j] = dp[i][j-1]+a[i][j];
			else
			   dp[i][j] = max(dp[i-1][j],dp[i][j-1])+a[i][j];
			//cout << dp[i][j] << " ";
		}
		//cout << endl;
	}
	
	printf("%d ",dp[n][m]);
	
	dfs(dp[n][m],n,m);

	printf("%d\n",ans);
    return 0;
}

 

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值