DP入门——迷宫行走方案3

题目描述

给你一个 (n)(m) 列( (1 le n,m le 100) )的二维迷宫,一开始你在迷宫的左上角的格子 ((1,1)) 处(我们用位置 ((x,y)) 来表示第 (x) 行第 (y) 列),你要走到右下角的格子 ((n,m)) 处 ,但是你是不能随便走的,每一步你只能往右移动一格,或者往下移动一个,并且你不能移动出迷宫的边界。
迷宫中的每一个格子都存放有一个宝箱,每个宝箱都存放有一定数量的金币,我们用 (a_{i,j}) 来表示格子 ((i,j)) 处存放的金币的数量( (0 le a_{i,j} le 1000) )。
你走到某个格子,你就能够拿到这个格子中的宝箱中的所有金币,请问你从迷宫的左上角走到迷宫的右下角能够获得的金币的最大数量是多少?

输入格式

输入的第一行包含两个整数 (n,m(1 le n,m le 10)) ,以空格分隔。
接下来 (n) 行,每行包含两个 (m) 个整数 (a_{i,j}(0 le a_{i,j} le 1000)) ,以一个空格分隔,用于表示二维迷宫中每个格子中的宝箱中存放的金币的数量。

输出格式

输出包含一个整数,表示从 ((1,1)) 走到 ((n,m)) 的所有方案中能够收获最多金币的那种方案对应的金币数。

样例输入

2 2
1 2
3 1

样例输出

5

本题涉及算法:动态规划。
我们设状态 (f[i][j]) 表示从 ((1,1)) 走到 ((i,j)) 的能够获得的最多的金币数量;
那么:

  • 对于 ((1,1)) 来说,(f[1][1] = a[1][1])
  • 对于除了 ((1,1)) 以外的所有第 (1) 行的元素 ((1,i)) 来说,因为 ((1,i)) 只有可能是从 ((1,i-1)) 走过来的,所以 (f[1][i] = a[1][i] + f[1][i-1]) ;
  • 对于除了 ((1,1)) 以外的所有第 (1) 列的元素 ((i,1)) 来说,因为 ((i,1)) 只有可能是从 ((i-1,1)) 走过来的,所以 (f[i][1] = a[i][1] + f[i-1][1]) ;
  • 对于其他的所有点 ((i,j)) ,因为 ((i,j)) 只能从 ((i-1,j))((i,j-1)) 两个点走过来,所以 (f[i][j] = a[i][j] + max(f[i-1][j],f[i][j-1]))

我们可以按照这个思路递推得到 (f[n][m]) 就是我们的答案。
实现代码如下:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 110;
int n, m, a[maxn][maxn], f[maxn][maxn];
int main() {
    cin >> n >> m;
    for (int i = 1; i <= n; i ++)
        for (int j = 1; j <= m; j ++)
            cin >> a[i][j];
    for (int i = 1; i <= n; i ++)
        for (int j = 1; j <= m; j ++)
            f[i][j] = a[i][j] + max(f[i-1][j], f[i][j-1]);
    cout << f[n][m] << endl;
    return 0;
}
原文地址:https://www.cnblogs.com/quanjun/p/13247113.html