day21 1015 摘花生 (线性DP)

这篇博客介绍了如何使用动态规划解决一个典型的线性DP问题——HelloKitty摘花生。HelloKitty在网格状的花生地中,只能向东或向南移动,目标是摘取最多的花生。通过建立状态转移方程`dp[i][j]=max(dp[i-1][j], dp[i][j-1])+arr[i][j]`,并初始化边界条件,博主展示了如何计算摘到最多花生的路径。Java代码实现给出了详细的解题思路。

1015. 摘花生

Hello Kitty想摘点花生送给她喜欢的米老鼠。

她来到一片有网格状道路的矩形花生地(如下图),从西北角进去,东南角出来。

地里每个道路的交叉点上都有种着一株花生苗,上面有若干颗花生,经过一株花生苗就能摘走该它上面所有的花生。

Hello Kitty只能向东或向南走,不能向西或向北走。

问Hello Kitty最多能够摘到多少颗花生。
在这里插入图片描述
输入格式
第一行是一个整数TTT,代表一共有多少组数据。

接下来是TTT组数据。

每组数据的第一行是两个整数,分别代表花生苗的行数RRR和列数 CCC

每组数据的接下来RRR行数据,从北向南依次描述每行花生苗的情况。每行数据有CCC个整数,按从西向东的顺序描述了该行每株花生苗上的花生数目MMM

输出格式
对每组输入数据,输出一行,内容为Hello Kitty能摘到得最多的花生颗数。

数据范围
1≤T≤100,1≤T≤100,1T100,
1≤R,C≤100,1≤R,C≤100,1R,C100,
0≤M≤10000≤M≤10000M1000
输入样例:

2
2 2
1 1
3 4
2 3
2 3 4
1 6 5

输出样例:

8
16

思路:

Hello Kitty只能向东或向南走,不能向西或向北走,也即只能向右或者向下走。

这是一个典型的线性dp问题。

我们把走到一个点看做一个状态,对Hello Kitty来说,走到一个点只有两种方式,一种是从上面下来走到该点,另一种是从左边过来走到该点。即要到达点(i,j)(i,j)(i,j),要么是从(i−1,j)(i−1,j)(i1,j)走到(i,j)(i,j)(i,j),要么是从点(i,j−1)i,j−1)i,j1)走到(i,j)(i,j)(i,j)

我们用dp[i][j]dp[i][j]dp[i][j]来代表走到点(i,j)(i,j)(i,j)一共摘到的花生。我们需要走到(n−1,m−1)(n - 1,m - 1)(n1,m1),所以可以得到状态转移方程: dp[i][j]=max(dp[i−1][j]),dp[i][j−1]))+arr[i][j]dp[i][j]=max(dp[i−1][j]),dp[i][j−1]))+arr[i][j]dp[i][j]=max(dp[i1][j]),dp[i][j1]))+arr[i][j]。根据转移方程,我们可以推出走到(n−1,m−1)(n - 1,m - 1)(n1,m1)处摘到的最多花生。

Java代码

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int T = scanner.nextInt();

        //共需要处理T组数据
        while(T-- != 0){
            int n = scanner.nextInt();
            int m = scanner.nextInt();
            int[][] arr = new int[n][m];
            int[][] dp = new int[n][m];
            //读入一组数据
            for(int i = 0;i < n;i++){
                for(int j = 0; j < m;j++){
                    arr[i][j] = scanner.nextInt();
                }
            }

            //1. 初始化dp
            dp[0][0] = arr[0][0];
            //第一行的只能从左边过来
            for(int j = 1;j < m;j++) dp[0][j] = dp[0][j - 1] + arr[0][j];
            //第一列只能从上面下来
            for(int i = 1;i < n;i++) dp[i][0] = dp[i - 1][0] + arr[i][0];
            //2. 计算dp
            for(int i = 1;i < n;i++){
                for(int j = 1;j < m;j++){
                    dp[i][j] = Math.max(dp[i - 1][j],dp[i][j - 1]) + arr[i][j];
                }
            }
            System.out.println(dp[n- 1][m - 1]);
        }
    }
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值