L3-3 寻宝路线

题目来源:天梯赛训练题

在一个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

 题意:

有一个m行n列的矩阵,计算从左上角方格(0,0)到右下角方格(m-1,n-1)的所有路径中,路径上方格中数字的和最大值是多少,并求最大和值的路径数量。

思路:

1. 先使用dp[][]数组来计算每一步的最大值,以及最大和值;

2. 使用dfs或bfs进行遍历即可,遍历到终点时记录最大和值出现的次数即可。在某个点遍历前,不仅要判断边界条件,还要判断该点遍历是否可以得到该步的最大值,否则则考虑下一个点。 否则dfs会超时,而bfs会内存超限。 

//L3-3 寻宝路线
#include <iostream>
using namespace std;
#define N 100
#include <queue>


int n,m;
int a[N][N];
int dp[N][N];
int ma = -100000000;	//记录最大值 
int c=0;		//最大值的个数 
int dx[]={0,1};
int dy[]={1,0};

void dfs(int x,int y,int sum)   	 //dfs  
{
	sum+=a[x][y];
	if(x==n-1&&y==m-1)		 //到达终点 
	{
		if(ma==sum)
            c++;
		return ;	
	}
    
    for(int i=0;i<2;i++)
    {
        int newX=x+dx[i];
        int newY=y+dy[i];
        //递归时既要考虑范围还要考虑是否可能为最大路径,有一点不是在最大路径上,则忽略该路径 
        if(newX<n&&newY<m&&sum+a[newX][newY]==dp[newX][newY])		//重点 
            dfs(newX,newY,sum);   		//向下或右走 
    }
}

void bfs(int x,int y)   	 //bfs  
{
	queue<pair<int,int>> qe;
	queue<int> value;
	qe.push({x,y});
	value.push(a[x][y]);
	int val,newX,newY,i;
	while(!qe.empty())
	{
		x=qe.front().first;
		y=qe.front().second;
		val=value.front();
		qe.pop();
		value.pop();
		
		if(x==n-1&&y==m-1)			//到达右下角 
		{
			if(val==ma)
				c++;
			continue;
		}
		
		for(i=0;i<2;i++)
		{
			newX=x+dx[i];
			newY=y+dy[i];
			if(newX<n&&newY<m&&val+a[newX][newY]==dp[newX][newY])	//重点,边界判断 + 路径判断 
			{
				qe.push({newX,newY});
				value.push(val+a[newX][newY]);
			}
		}
	}	
}


int mafind()		//找最大值 
{
	for(int i=0;i<n;i++)
	{
		for(int j=0;j<m;j++)
		{
			if(i==0&&j==0)
				dp[i][j]=a[i][j];
			else if(j==0)
				dp[i][j]=dp[i-1][j]+a[i][j];
			else if(i==0)
				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]; 	
		}
	}
	return dp[n-1][m-1];
}
int main()
{
	cin>>n>>m;
	int i,j;
	for(i=0;i<n;i++)	         //输入 
	for(j=0;j<m;j++)
		cin>>a[i][j];
	
	ma=mafind();	             //找最大值 

//	dfs(0,0,0);                  //使用dfs进行深度遍历 
 	bfs(0,0);	          		 //bfs也可以做 
	
	cout<<ma<<" "<<c<<endl;		 //输出 
	
	return 0;
 } 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值