寻宝路线

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

猜你喜欢

转载自blog.csdn.net/qq_40511966/article/details/88607675