AcWing 1015. 摘花生(DP)

文章介绍了如何用动态规划解决一类类似于数字三角形的问题,涉及状态表示为`f(i,j)`表示到达`(i,j)`的最大花生数,状态转移方程为`f(i,j)=max(f(i-1,j)+w[i][j],f(i,j-1)+w[i][j])`,并提供了C++代码实现。
摘要由CSDN通过智能技术生成

一、问题描述

在这里插入图片描述

二、思路分析

这道题非常类似我们数字三角形那道题,大家如果这道题不会的话,可以先去看作者之前写的数字三角形问题的解法,然后再回来看这道题,或许就能有思路了。
传送门:
DP母题——数字三角形

1、状态表示

f ( i , j ) f(i,j) f(i,j)表示的是从起点 ( 0 , 0 ) (0,0) (0,0)走到 ( i , j ) (i,j) (i,j)的过程中,可能摘走的花生的数目中的最大值

2、状态转移

状态转移方程的书写,要么看当前状态能够推导出哪些状态,要么看当前状态能够从哪些状态推导而来。这两个角度也是我们在做DP问题的时候经常使用的方法。

当前的点要么从正上方的点移动而来,要么由左边的点移动而来。

我们在这两种可能当中,取一个花生数目最多的状态, 再加上当前状态的花生数目就是我们的当前的状态。

f ( i , j ) = { m a x ( f ( i − 1 , j ) , + f ( i , j − 1 ) ) + w [ i ] [ j ] i , j ≥ 1 f ( i − 1 , j ) + w [ i ] [ j ] i ≥ 1 , j < 1 f ( i , j − 1 ) + w [ i ] [ j ] j ≥ 1 , i < 1 f(i,j)= \begin{cases} max \big( f(i-1,j),+f(i,j-1)\big)+w[i][j] & i,j\geq 1\\ f(i-1,j)+w[i][j] &i\geq 1,j<1\\ f(i,j-1)+w[i][j] &j\geq 1,i<1 \end{cases} f(i,j)= max(f(i1,j),+f(i,j1))+w[i][j]f(i1,j)+w[i][j]f(i,j1)+w[i][j]i,j1i1,j<1j1,i<1

3、循环设计

循环设计的设计要符合拓扑排序,说白了就是要在计算当前状态的时候,已经计算出了等式右边子问题的状态。
这道题很明显,i 和 j 谁做外循环都可以,所以大家二选一即可。

4、初末状态

初始化的是最小子问题,这道题的话,就是我们站在起点的时候,所携带的花生数目。很明显,站在起点(0,0)的初始状态,就是(0,0)点的花生数目。

末状态是为了能够表示出答案并输出。
这道题就是 f [ r − 1 ] [ c − 1 ] f[r-1][c-1] f[r1][c1],因为下标从0开始,所以右下角的坐标-1。

三、代码

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=110;
int f[N][N],g[N][N];
int t,r,c;
int main()
{
    cin>>t;
    while(t--)
    {
        scanf("%d%d",&r,&c);
        for(int i=0;i<r;i++)
            for(int j=0;j<c;j++)
                scanf("%d",&g[i][j]);
        
        f[0][0]=g[0][0];
        for(int i=0;i<r;i++)
        {
            for(int j=0;j<c;j++)
            {
                if(j<1&&i>=1)
                    f[i][j]=f[i-1][j]+g[i][j];
                else if(i<1&&j>=1)
                    f[i][j]=f[i][j-1]+g[i][j];
                else if(i>=1&&j>=1)
                    f[i][j]=max(f[i][j-1]+g[i][j],f[i-1][j]+g[i][j]);
            }
        }
        cout<<f[r-1][c-1]<<endl;
    }
    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值