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

题目描述

给你一个 (n)(m) 列的二维迷宫,一开始你在迷宫的左上角的格子 ((1,1)) 处(我们用位置 ((x,y)) 来表示第 (x) 行第 (y) 列),你要走到右下角的格子 ((n,m)) 处 ,但是你是不能随便走的,每一步你只能往右移动一格,或者往下移动一个,并且你不能移动出迷宫的边界,请问你有多少种不同的移动方案。
说明:只要从起点到终点的移动路线不同,那么我们就说它们是不同的移动方案。比如:假设 (n = m = 2),那么从左上角 ((1,1)) 移动到右下角 ((2,2)) 共有(2) 种移动方案:

  • ((1,1) Rightarrow (1,2) Rightarrow (2,2))
  • ((1,1) Rightarrow (2,1) Rightarrow (2,2))

输入格式

输入一行包含两个整数 (n,m(1 le n,m le 10)) ,以空格分隔。

输出格式

输出包含一个整数,表示从 ((1,1)) 走到 ((n,m)) 的方案数。

样例输入

2 2

样例输出

2

本题涉及算法:动态规划。
我们设状态 (f[i][j]) 表示从 ((1,1)) 走到 ((i,j)) 的方案总数;
那么:

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

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

#include <bits/stdc++.h>
using namespace std;
const int maxn = 11;
int n, m, f[11][11];
int main() {
    cin >> n >> m;
    for (int i = 1; i <= n; i ++) {
        for (int j = 1; j <= m; j ++) {
            if (i == 1 && j == 1) f[1][1] = 1;
            else f[i][j] = f[i-1][j] + f[i][j-1];
        }
    }
    cout << f[n][m] << endl;
    return 0;
}

代码说明:因为所有的 (f[0][j])(f[i][0]) 都为 (0) , 所以对所有除了 ((1,1)) 以外的第一行或者第一列的元素 ((i,j)) ,我们同样可以使用推导方程:(f[i][j] = f[i-1][j] + f[i][j-1]) ,而不需要特殊判断。

原文地址:https://www.cnblogs.com/quanjun/p/13247084.html