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