1015. 摘花生
Hello Kitty想摘点花生送给她喜欢的米老鼠。
她来到一片有网格状道路的矩形花生地(如下图),从西北角进去,东南角出来。
地里每个道路的交叉点上都有种着一株花生苗,上面有若干颗花生,经过一株花生苗就能摘走该它上面所有的花生。
Hello Kitty只能向东或向南走,不能向西或向北走。
问Hello Kitty最多能够摘到多少颗花生。
输入格式
第一行是一个整数$T$,代表一共有多少组数据。
接下来是$T$组数据。
每组数据的第一行是两个整数,分别代表花生苗的行数$R$和列数 $C$。
每组数据的接下来$R$行数据,从北向南依次描述每行花生苗的情况。每行数据有$C$个整数,按从西向东的顺序描述了该行每株花生苗上的花生数目$M$。
输出格式
对每组输入数据,输出一行,内容为Hello Kitty能摘到得最多的花生颗数。
数据范围
$1≤T≤100,$
$1≤R,C≤100,$
$0≤M≤1000$
输入样例:
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−1,j)$走到$(i,j)$,要么是从点($i,j−1)$走到$(i,j)$。
我们用$dp[i][j]$来代表走到点$(i,j)$一共摘到的花生。我们需要走到$(n - 1,m - 1)$,所以可以得到状态转移方程: $dp[i][j]=max(dp[i−1][j]),dp[i][j−1]))+arr[i][j]$。根据转移方程,我们可以推出走到$(n - 1,m - 1)$处摘到的最多花生。
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]);
}
}
}