一、题目描述
题目链接
二、解题思路
因为只是一道多阶段最优化决策问题,虽然它长得有点像dfs或者bfs,但是用那两种方法就会无情的超时,此时注意:dijkstra的话可以返回(就是它会把所有的花生都算上),结合这四种算来看,动态规划的做法是最优的,所以就要采用动态规划来做这道题。
1、数学建模
令dpi,j表示第i行,第j列的最多可以获得的最多的花生的数量。
dp数组 | 1 | 2 |
---|---|---|
1 | 1 | 2 |
2 | 4 | 8 |
ans=dp2,2=8
dp数组 | 1 | 2 | 3 |
---|---|---|---|
1 | 2 | 5 | 9 |
2 | 3 | 11 | 16 |
ans=dp2,3=16
2、状态转移方程
从上面列的表来看,很容易找到规律,其状态转移方程如下:
dpi,j=max(dpi-1,j,dpi,j-1)+Ai,j
原因
其实原因也很好想,因为每一次的选择路径只能从上面或者右面达到这个点,所以这个点的最大的能够得到的花生的数量就与上面的点和左面的点有关,而且,也与自己的花生的数量有关,就得到了上面的式子。
注意
在循环求解(递推)是要注意,只能从上到下,从左到右枚举dp数组。
3、边界(初始化)
其实只要当dp0,j=dpi,0=0时,就可以了,也可以把dp1,1算出来,两种方法都可以。
三、代码
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int T,n,m,A[110][110],dp[110][110];
int main()
{scanf("%d",&T);while(T--){memset(dp,-1,sizeof(dp));scanf("%d%d",&n,&m);for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)scanf("%d",&A[i][j]);dp[1][1]=A[1][1];for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){if(dp[i][j]==-1)dp[i][j]=max(dp[i-1][j],dp[i][j-1])+A[i][j];}}printf("%d\n",dp[n][m]);}return 0;
}