有一个 N x N 的方格,每一个格子都有一些金币,只要站在格子里就能拿到里面的金币。你站在最左上角的格子里,每次可以从一个格子走到它右边或下边的格子里。请问如何走才能拿到最多的金币。
输入输出格式
输入格式
第一行有一个整数 N。
之后 N 行有 N 个整数,表示数组数组的所有元素,每个整数用一个空格隔开。
输出格式
一个整数。
输入输出样例1
输入
1
3
输出
3
输入输出样例2
输入
3
1 3 3
2 2 2
3 1 2
输出
11
说明提示
1≤n≤1000
//使用动态规划算法解决
#include <iostream>
#include <vector>
#include <algorithm>
//c++常用头文件
using namespace std;
int main() {
int N;
cin >> N;
// 定义二维数组来存储方格中的金币数量
vector<vector<int>> grid(N, vector<int>(N));
// 读取方格中的金币数量
for (int i = 0; i < N; ++i) {
for (int j = 0; j < N; ++j) {
cin >> grid[i][j];
}
}
// 定义二维数组dp来存储到达每个格子能获得的最大金币数
vector<vector<int>> dp(N, vector<int>(N, 0));
// 初始化左上角的格子
//从题目意思来看,我只能向右边或者下面移动,将金币进行累加
//换言之,要想得到靠近最左边与最上面的只能,沿着格子(数组)的边界遍历
dp[0][0] = grid[0][0];
// 初始化第一行
for (int j = 1; j < N; ++j) {
dp[0][j] = dp[0][j - 1] + grid[0][j];
}
// 初始化第一列
for (int i = 1; i < N; ++i) {
dp[i][0] = dp[i - 1][0] + grid[i][0];
}
//在动态规划题目中,dp数组使用核心,由于他有特殊的含义,根据题目设定而变化
//此处的dp数组代表在从位置(0,0)到达位置(i,j)处时,这些路径中能得到的最大金币数量
// 填充dp数组
for (int i = 1; i < N; ++i) {
for (int j = 1; j < N; ++j) {
// 状态转移方程:当前格子的最大金币数等于上方或左方格子的最大金币数加上当前格子的金币数
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]) + grid[i][j];
//最终结果就在最右下方,由于从题目中也看得出来,我们从最左上角到达最右角出去。
}
}
// 输出右下角格子的最大金币数
cout << dp[N - 1][N - 1] << endl;
return 0;
}