蒜国地域是一个 nn 行 mm 列的矩阵,下标均从 11 开始。蒜国有个美丽的城堡,在坐标 (n,m)(n,m) 上,蒜头君在坐标 (1,1)(1,1) 的位置上。蒜头君打算出发去城堡游玩,游玩结束后返回到起点。在出发去城堡的路上,蒜头君只会选择往下或者往右走,而在返回的路上,蒜头君只会选择往上或者往左走,每次只能走一格。已知每个格子上都有一定数量的蒜味可乐,每个格子至多经过一次。
现在蒜头君请你来帮他计算一下,如何计划来回行程,可以收集到最多的蒜味可乐。
输入格式
第一行输入两个整数 n,m(1≤n,m≤50)n,m(1≤n,m≤50),表示蒜国是一个 nn 行 mm 列的矩阵。
接下来输入 nn 行,每行输入 mm 个整数,代表一个 n×mn×m 的矩阵,每个整数代表对应位置上的蒜味可乐数量,每行的每两个整数之间用一个空格隔开。其中蒜头君的位置和城堡的位置上没有蒜味可乐,用 00 表示,其余位置上的整数范围在 1,100内。
输出格式
输出一行,输出一个整数,表示蒜头君在来回路上能收集到的蒜味可乐的最大值。
样例输入
3 3
0 2 9
4 8 6
2 7 0
样例输出
36
我的解题思路:
我们先分阶段,把题意看做同时出发的两个人,同时到达终点(n,m),这两个人一共收集的最大数量。
因此dpik看做同一时刻一个人到达(i,j),一个人到达(k,l)所收集可乐的最大数量。
因此这一时刻的最大数量等于上一时刻的最大数量+刚刚捡到的可乐数量。
dpik=max(max(max(dpi-1k-1,dpi-1k),dpik-1),dpik)+ai+ak;
特殊情况:
1.两条路不能交叉,即当i==j&&k==l时,要使dpik=0;这样,这条路之后不会有人选,相当于这种情况不存在了。
2.最后,dpnn一定为0,因为1.所以,我们只需要知道当一个人到达(n-1,m)/(n,m-1)时,若要满足两人可乐数最大,
另一个人一定达到(n,m-1)/(n-1,m)处。答案输出dpnn-1即可。
3.把dp5151放在main函数外,全局变量所在的系统stack较大。
详情见代码:
#include<iostream>
#include<algorithm>
using namespace std;
int dp[51][51][51][51];
int a[51][51];
int main(){
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
cin>>a[i][j];
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
for(int k=1;k<=n;k++){
for(int l=1;l<=m;l++){
if(i==k&&j==l) continue;
dp[i][j][k][l]=
max(max(max(dp[i-1][j][k-1][l],dp[i-1][j][k][l-1]),dp[i][j-1][k-1][l]),
dp[i][j-1][k][l-1])+a[i][j]+a[k][l];
}
}
}
}
cout<<dp[n-1][m][n][m-1];
}