问题描述
有一个N x N的方格,每一个格子都有一些金币,只要站在格子里就能拿到里面的金币。你站在最左上角的格子里,每次可以从一个格子走到它右边或下边的格子里。请问如何走才能拿到最多的金币。
输入格式
第一行输入一个正整数n。
以下n行描述该方格。金币数保证是不超过1000的正整数。输出格式
最多能拿金币数量。
样例输入
3
1 3 3
2 2 2
3 1 2样例输出
11
数据规模和约定
n<=1000
这是经典的动态规划问题,运用dp数组来记录在每一格所拿到的最大金币数。
先声明一个二位dp数组,用来记录开始金币数和后来的最大金币数。初始化每格的金币数后,再对第一行和第一列进行最大值计算(相当于只向右走或只向下走能收集到的最大金币数)。然后对走中间的情况进行判断,我们只需比较它左边和上面的数的大小,选大的数与所在格子的金币数相加,便得到了所在格子所能拿到的最大金币数
具体代码如下:
#include<iostream>
using namespace std;
#define N 1000
int dp[N][N];
int main() {
int n;
cin >> n;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
cin >> dp[i][j];
}
}
//初始化第一行的最大和
for (int i = 2; i <= n; i++) {
dp[1][i] = dp[1][i - 1] + dp[1][i];
}
//初始化第一列的最大和(两个循环可放在一起,分开方便理解)
for (int i = 2; i <= n; i++) {
dp[i][1] = dp[i - 1][1] + dp[i][1];
}
//求中间数的最大和
for (int i = 2; i <= n; i++) {
for (int j = 2; j <= n; j++) {
if (dp[i][j - 1] > dp[i - 1][j]) {
dp[i][j] = dp[i][j - 1] + dp[i][j];
}
else {
dp[i][j] = dp[i - 1][j] + dp[i][j];
}
}
}
cout << dp[n][n] << endl;
return 0;
}
动态规划是一种常见的算法思想,大家要好好学习,熟练运用。 加油!!!