首页 >

走方格的方案数

下面按照你的要求来讲:先给完整代码,再讲解题思路,再解释为什么要用到这些语法、数组、循环,最后逐行解释代码。


一、完整代码

#include <iostream>
using namespace std;

int main() {
    int n, m;
    cin >> n >> m;

    int dp[10][10];

    for (int i = 0; i <= n; i++) {
        for (int j = 0; j <= m; j++) {
            if (i == 0 || j == 0) {
                dp[i][j] = 1;
            } else {
                dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
            }
        }
    }

    cout << dp[n][m] << endl;
    return 0;
}

二、题目要求是什么意思?

题目给你一个n × m的方格。

你从左上角出发,要走到右下角。

每一步只能:

向右走
或者
向下走

问你一共有多少种不同走法。

例如输入:

2 2

表示有一个2 × 2的方格。

从左上角走到右下角,需要走:

2 次向下
2 次向右

所有走法有:

右 右 下 下
右 下 右 下
右 下 下 右
下 右 右 下
下 右 下 右
下 下 右 右

一共6种,所以输出:

6

三、解题思路

这道题可以用 动态规划 来做。

动态规划可以简单理解为:

把大问题拆成小问题,先算出小位置的走法数量,再推出后面位置的走法数量。

我们定义:

dp[i][j]

表示:

从左上角走到第 i 行、第 j 列这个格点,一共有多少种走法。

比如:

dp[2][2]

就表示:

从左上角走到第 2 行、第 2 列这个位置的走法数量。

因为只能向右或向下走,所以到达某个位置只能从两个方向来:

1. 从上面走下来
2. 从左边走过来

也就是说:

dp[i][j]

只能由:

dp[i - 1][j]

和:

dp[i][j - 1]

推出。

所以公式是:

dp[i][j] = dp[i - 1][j] + dp[i][j - 1];

意思是:

到达当前位置的走法数量
=
到达上面位置的走法数量
+
到达左边位置的走法数量

四、为什么要用二维数组dp[10][10]?

代码中有:

int dp[10][10];

这是一个二维数组。

二维数组可以理解成一个表格。

因为这道题是走方格,需要记录每个位置的走法数量。

例如:

dp[0][0]  dp[0][1]  dp[0][2]
dp[1][0]  dp[1][1]  dp[1][2]
dp[2][0]  dp[2][1]  dp[2][2]

每一个dp[i][j]都表示走到这个位置的方法数。

题目范围是:

1 <= n, m <= 8

但是我们要用到下标:

0 到 n
0 到 m

最大就是:

0 到 8

所以数组至少需要能访问:

dp[8][8]

数组开成:

int dp[10][10];

足够使用。

为什么不是dp[8][8]?

因为 C++ 数组下标从0开始。

如果写:

int dp[8][8];

它的合法下标是:

0 到 7

不能访问dp[8][8]。

所以这里开大一点:

int dp[10][10];

更安全,也更容易理解。


五、为什么第一行和第一列都是 1?

代码中有:

if (i == 0 || j == 0) {
    dp[i][j] = 1;
}

这是初始化边界。

1. 第一行为什么是 1?

第一行表示:

i == 0

也就是最上面一行。

在最上面一行,只能一直向右走。

例如走到:

dp[0][3]

只能这样走:

右 右 右

没有其他选择,所以只有1种走法。

因此:

dp[0][0] = 1
dp[0][1] = 1
dp[0][2] = 1
dp[0][3] = 1

2. 第一列为什么是 1?

第一列表示:

j == 0

也就是最左边一列。

在最左边一列,只能一直向下走。

例如走到:

dp[3][0]

只能这样走:

下 下 下

没有其他选择,所以也是1种走法。

因此:

dp[0][0] = 1
dp[1][0] = 1
dp[2][0] = 1
dp[3][0] = 1

六、为什么要用两个for循环?

代码中有:

for (int i = 0; i <= n; i++) {
    for (int j = 0; j <= m; j++) {
        ...
    }
}

因为dp是二维数组,相当于一个表格。

表格有行和列。

外层循环控制行:

for (int i = 0; i <= n; i++)

内层循环控制列:

for (int j = 0; j <= m; j++)

也就是说,这两个循环会把每一个格点都算一遍。

例如n = 2, m = 2时,会计算:

dp[0][0]  dp[0][1]  dp[0][2]
dp[1][0]  dp[1][1]  dp[1][2]
dp[2][0]  dp[2][1]  dp[2][2]

最后答案就是:

dp[2][2]

也就是:

dp[n][m]

七、为什么不是循环到< n,而是<= n?

代码中写的是:

for (int i = 0; i <= n; i++)

而不是:

for (int i = 0; i < n; i++)

原因是题目中的n × m个方格,对应的格点是:

从 0 到 n
从 0 到 m

比如2 × 2的方格,格点不是只有:

0, 1

而是:

0, 1, 2

也就是说,需要算到:

dp[2][2]

所以循环必须写:

i <= n
j <= m

这样才能包含终点位置。


八、代码中用到的语法和函数解释

1.#include <iostream>是什么?

#include <iostream>

这是引入输入输出库。

因为代码中用到了:

cin
cout
endl

这些都属于 C++ 的输入输出功能。

它们定义在<iostream>这个头文件中。

如果不写:

#include <iostream>

编译器就可能不认识cin和cout。


2.using namespace std;是什么?

using namespace std;

C++ 标准库中的很多东西都放在std这个命名空间中。

例如完整写法应该是:

std::cin
std::cout
std::endl

写了:

using namespace std;

之后,就可以简写成:

cin
cout
endl

这样代码更短,更适合初学者。


3.int main()是什么?

int main() {

这是程序的主函数。

C++ 程序运行时,会从main函数开始执行。

int表示这个函数最后会返回一个整数。

最后的:

return 0;

就是返回整数0,表示程序正常结束。


4.cin >> n >> m;是什么?

cin >> n >> m;

cin是输入对象。

>>是输入运算符。

这句代码表示从输入中读取两个整数,分别放进变量n和m。

例如输入:

2 2

执行后:

n = 2;
m = 2;

也可以理解成:

cin >> n;
cin >> m;

只不过写在一行更加简洁。


5.cout << dp[n][m] << endl;是什么?

cout << dp[n][m] << endl;

cout是输出对象。

<<是输出运算符。

dp[n][m]是最终答案。

endl表示换行。

例如:

dp[n][m] = 6;

那么输出就是:

6

6.||是什么?

代码中有:

if (i == 0 || j == 0)

||表示“或者”。

这句话的意思是:

如果 i 等于 0,或者 j 等于 0

只要其中一个条件成立,整体就成立。

也就是说:

在第一行,或者在第一列

都要设置为1。


7.==是什么?

代码中有:

i == 0
j == 0

==表示判断是否相等。

它和=不一样。

i == 0

表示判断i是否等于0。

i = 0

表示把0赋值给i。

初学者要特别注意:

判断相等用 ==
赋值用 =

8.dp[i - 1][j]和dp[i][j - 1]是什么?

dp[i - 1][j]

表示当前位置上面的格点。

因为行号减少1,列号不变。

dp[i][j - 1]

表示当前位置左边的格点。

因为行号不变,列号减少1。

例如当前位置是:

dp[2][3]

那么它上面的位置是:

dp[1][3]

它左边的位置是:

dp[2][2]

所以:

dp[2][3] = dp[1][3] + dp[2][2];

九、逐行解释代码

第 1 行

#include <iostream>

引入输入输出库。

因为程序需要从键盘读入n和m,还需要输出答案。

所以需要使用:

cin
cout
endl

这些功能都来自<iostream>。


第 2 行

using namespace std;

使用标准命名空间。

写了这一行后,可以直接使用:

cin
cout
endl

不用写成:

std::cin
std::cout
std::endl

第 4 行

int main() {

定义主函数。

程序从这里开始执行。


第 5 行

int n, m;

定义两个整数变量:

n 表示方格的行数
m 表示方格的列数

例如输入:

2 2

那么:

n = 2;
m = 2;

第 6 行

cin >> n >> m;

从输入中读取两个整数,分别存入n和m。

比如输入:

2 2

执行后:

n 保存 2
m 保存 2

第 8 行

int dp[10][10];

定义一个二维数组dp。

它用来保存每个位置的走法数量。

其中:

dp[i][j]

表示:

从左上角走到第 i 行、第 j 列,一共有多少种走法。

数组大小写10 × 10,是因为题目中n和m最大是8,我们访问到dp[8][8]就够了,开10更安全。


第 10 行

for (int i = 0; i <= n; i++) {

外层循环,控制行号i。

从第0行开始,一直循环到第n行。

为什么是<= n?

因为终点是:

dp[n][m]

所以必须把第n行也算进去。


第 11 行

for (int j = 0; j <= m; j++) {

内层循环,控制列号j。

从第0列开始,一直循环到第m列。

和行号一样,终点是:

dp[n][m]

所以第m列也必须计算。


第 12 行

if (i == 0 || j == 0) {

判断当前位置是否在第一行或者第一列。

i == 0

表示第一行。

j == 0

表示第一列。

||

表示“或者”。

也就是说:

如果当前位置在第一行,或者当前位置在第一列

就进入这个if。


第 13 行

dp[i][j] = 1;

如果当前位置在第一行或第一列,那么走到这里的方法数是1。

原因是:

第一行只能一直向右走
第一列只能一直向下走

所以没有其他路线。


第 14 行

} else {

如果当前位置不在第一行,也不在第一列,就进入else。

这种位置可以从上面来,也可以从左边来。


第 15 行

dp[i][j] = dp[i - 1][j] + dp[i][j - 1];

这是动态规划的核心公式。

当前位置的走法数量等于:

上面位置的走法数量 + 左边位置的走法数量

对应代码就是:

dp[i - 1][j]

表示上面位置。

dp[i][j - 1]

表示左边位置。

所以:

dp[i][j] = dp[i - 1][j] + dp[i][j - 1];

例如计算:

dp[1][1]

它可以从:

dp[0][1]

走下来,也可以从:

dp[1][0]

走过来。

所以:

dp[1][1] = dp[0][1] + dp[1][0];

因为:

dp[0][1] = 1;
dp[1][0] = 1;

所以:

dp[1][1] = 2;

第 20 行

cout << dp[n][m] << endl;

输出最终答案。

因为:

dp[n][m]

表示从左上角走到右下角的方案数。

所以直接输出它。

例如:

dp[2][2] = 6;

输出就是:

6

第 21 行

return 0;

表示程序正常结束。

这是 C++ 程序常见写法。


十、用示例完整走一遍

输入:

2 2

表示要计算:

dp[2][2]

初始化和计算过程如下。

第一行和第一列都是1:

dp[0][0] = 1
dp[0][1] = 1
dp[0][2] = 1

dp[1][0] = 1
dp[2][0] = 1

然后计算其他位置。

计算dp[1][1]

dp[1][1] = dp[0][1] + dp[1][0];

也就是:

dp[1][1] = 1 + 1 = 2

计算dp[1][2]

dp[1][2] = dp[0][2] + dp[1][1];

也就是:

dp[1][2] = 1 + 2 = 3

计算dp[2][1]

dp[2][1] = dp[1][1] + dp[2][0];

也就是:

dp[2][1] = 2 + 1 = 3

计算dp[2][2]

dp[2][2] = dp[1][2] + dp[2][1];

也就是:

dp[2][2] = 3 + 3 = 6

最后表格是:

1 1 1
1 2 3
1 3 6

所以输出:

6

十一、为什么这道题可以用动态规划?

因为走到一个位置的方法数,依赖于它前面的两个位置:

上面的位置
左边的位置

而这些位置的方法数可以提前算出来。

也就是说:

小问题:走到前面位置有多少种方法
大问题:走到当前位置有多少种方法

通过小问题推出大问题,这就是动态规划。

这道题的状态转移公式是:

dp[i][j] = dp[i - 1][j] + dp[i][j - 1];

边界条件是:

dp[i][0] = 1;
dp[0][j] = 1;

最终答案是:

dp[n][m];

十二、这道题涉及的核心知识点

这份代码主要用到了:

1. cin 输入
2. cout 输出
3. 二维数组
4. for 循环
5. if else 判断
6. 动态规划思想
7. || 或者运算符
8. == 判断相等

其中最关键的是:

int dp[10][10];

用来保存每个位置的走法数。

以及:

dp[i][j] = dp[i - 1][j] + dp[i][j - 1];

用来根据上面和左边的位置推出当前位置的走法数。

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;


public class Main {
    public static int findWays(int m,int n){
        int[] rec=new int[n];
        rec[0]=1;
        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){
                if(j==0) rec[j]=rec[j];
                else if(i==0) rec[j]=rec[j-1];
                else rec[j]=rec[j-1]+rec[j];
            }
        }
        return rec[n-1];
    }

    public static void main(String[] args)throws IOException {
        //读入和输出的方式要注意,使用bufferedReader中的readLine可以很好知道是否到了末尾
        BufferedReader bReader = new BufferedReader(new InputStreamReader(System.in));
        String line=null;
        while((line=bReader.readLine())!=null) {
            int n=Integer.valueOf(line.substring(0,line.indexOf(" ")));
            int m=Integer.valueOf(line.substring(line.indexOf(" ")+1));
            System.out.println(findWays(n+1, m+1));
        }
    }
}

发表于 2020-06-08 12:06:52 回复(1)
#include<stdio.h>

int main()
{
    int a, b;
    while(scanf("%d %d",&a,&b) != EOF)
    {
        int c = 1, d = 1;
        for(int i = 1; i <= a; i++)
        {
            c *= i;
        }
        for(int j = b + 1; j <= a + b; j++)
        {
            d *= j;
        }
        printf("%d\n", d/c);
    }
}

发表于 2021-08-11 20:24:54 回复(0)
#include <iostream>
using namespace std;

int f(int a){
    if(a==1) return 1;
    return a*f(a-1);
}

int main(){
    int n,m;
    while(cin>>n>>m){
        cout<<f(n+m)/f(n)/f(m)<<'\n';
    }
}
发表于 2021-07-20 00:04:37 回复(0)
get_str = input().split(' ')
n, m = int(get_str[0]), int(get_str[1])
# (n+1)*(m+1)的二维dp数组
dp = [[0 for _ in range(m+1)] for _ in range(n+1)]
for i in range(n+1):
    for j in range(m+1):
        # dp数组初始化
        # 原点时0种走法
        if i==0 and j==0:
            dp[i][j] = 0
        # 从原点向下走一步共1种走法
        # elif i==0 and j==1:
        # 这里可以考虑优化?当退到左边界或上边界时仅剩一种走法
        elif i==0:
            dp[i][j] = 1
        # 从原点向右走一步共1种走法
        # elif i==1 and j==0:
        elif j==0:
            dp[i][j] = 1
        # [i][j]点的走法=左边一个点走法+上面一个点的走法
        # 即:dp[i][j] = dp[i-1][j] + dp[i][j-1]
        else:
            dp[i][j] = dp[i-1][j] + dp[i][j-1]
print(dp[n][m])

发表于 2022-07-30 17:46:31 回复(0)
#include <iostream>

using namespace std;

int fun(int num);

int main()
{
    int m=0, n=0;
    cin>>m>>n;
    cout<<fun(n+m)/(fun(m)*fun(n))<<endl;
    return 0;
}

int fun(int num)
{
    int sum=1;
    for(int i=2;i<=num;i++)
    {
        sum*=i;
    }
    return sum;
}

发表于 2022-05-12 20:49:29 回复(1)
import java.util.*;

public class Main {
    public static void main(String[] args) {

        Scanner sc = new Scanner(System.in);

        while (sc.hasNextInt()){

            int n = sc.nextInt();
            int m = sc.nextInt();
            int countUp = n;
            int countDown = n+m;
            int num = n;
            int zzz = n+m;
//            for (int a=n;a>1;--a){
//                    countUp = countUp*(a-1);
//                    countDown = countDown*(--countDown);
//            }
            while (num>1){
                countUp = countUp*(num-1);
                countDown = countDown*(zzz-1);
                num--;
                zzz--;
            }
            int count = countDown/countUp;

            System.out.println(count);
        }

    }
}

发表于 2021-11-26 01:19:31 回复(0)
方法1:
//数学方法,相当于一共要走(n+m)步,其中往右走要走n步,问题是在(n+m)步里哪些步是
//往右走。相当于在(n+m)个中取m个有多少种组合的问题。
import java.util.Scanner;

public class Main {

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        
        while(sc.hasNext()){
            int n = sc.nextInt();
            int m = sc.nextInt();
            
            System.out.println(combination(n, n+m));
        }
        sc.close();
    }
    
    public static int combination(int m, int n){//排列C(m,n)
        int above = factorial(n);
        int below = factorial(n-m) * factorial(m);
        return above / below;
    }
    
    public static int factorial(int n){//阶乘
        if(n>1){
            return n*factorial(n-1);
        }
        return n;
    }
}

方法2:把问题解法定为f(n,m),从左上角第1个点开始,如果往右走1步,剩下的问题就变成了f(n-1,m); 如果一开始往下走一步,剩下的问题就变成f(n,m-1), 一直递归,就有了f(n,m)=f(n-1,m)+f(n,m-1)。
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        
        while(sc.hasNext()){
            int m = sc.nextInt();
            int n = sc.nextInt();
            System.out.println(count(m,n));
        }
        
        sc.close();
    }
    
    public static int count(int m, int n){
        
        if(m==0 || n==0){
            return 1;
        }
            
        return count(m-1,n)+count(m,n-1);
        
        
    }
    
}

发表于 2021-10-27 10:46:50 回复(0)
动态规划:
while True:
    try:
        n,m = map(int, input().split())

        dp = [[1 for _ in range(m+1)] for _ in range(n+1)]
        for i in range(1,n+1):
            for j in range(1,m+1):
                temp = dp[i-1][j-1]*2
                temp1 = 0
                temp2 = 0

                for k in range(i-1):
                    temp1 += dp[k][j-1]
                for l in range(j-1):
                    temp2 += dp[i-1][l]
                dp[i][j] = temp+temp1+temp2
        print(dp[n][m])
    except:
        break

发表于 2021-01-26 15:57:35 回复(0)
C++,经典递归系列

#include <bits/stdc++.h>
using namespace std;
int count(int n, int m){
    if(n==0||m==0)
        return 1;
    return count(n-1,m)+count(n,m-1);
}
int main(){
    int n,m;
    while(cin>>n>>m){
        cout<<count(n,m)<<endl;
    }
    return 0;
}

发表于 2020-08-05 13:58:33 回复(0)
思路: 动态规划
import sys

def f(n,m):
    if min(n,m)==1:
        return 1 + max(n,m)
    else:
        return f(n,m-1) + f(n-1,m)

for s in sys.stdin:
    s = s.strip().split(" ")
    r = f(int(s[0]), int(s[1]))
    print(r)


编辑于 2020-06-07 22:53:17 回复(0)
#include <iostream>
#include <vector>

using namespace std;

int main(){
    int m, n;
    while(cin >> m >> n){
        vector<vector<int>> F(m + 1, vector<int>(n + 1, 1));
        for(int i = 1; i < m + 1; ++i){
            for(int j = 1; j < n + 1; ++j){
                F[i][j] = F[i - 1][j] + F[i][j - 1];
            }
        }
        cout << F[m][n] << endl;
    }
    return 0;
}

发表于 2020-06-04 09:49:41 回复(0)
#include<iostream>
(720)#include<vector>
using namespace std;
int main()
{
    int dfs(int n,int m);
    int n,m;
    while(cin>>n>>m)//n是列,m是行
    {
       vector<vector<int>>dp(m+1,vector<int>(n+1,1));
        for(int i=1;i<=m;i++)
        {
            for(int j=1;j<=n;j++)
            {
               dp[i][j]=dp[i-1][j]+dp[i][j-1];
            }
        }
        cout<<dp[m][n]<<endl;
        //cout<<dfs(n,m)<<endl;
    }
}
int dfs(int n,int m)
{
    if(m==0&&n==0)
        return 1;
    if(m>=0&&n>=0)
    {
        return dfs(n-1,m)+dfs(n,m-1);
    }
    return 0;
}
里面两种解法,一个dp,一个dfs
发表于 2020-04-16 12:08:18 回复(1)
#include <stdio.h>
(737)#include <string.h>

int n,m,sum,chess[128][128];

void DFS(int x,int y)    //深度优先搜索
{
	chess[x][y] = 1;
	if(x==m && y==n)
	{
		sum++;
		chess[x][y]=0;	
		return;
	}
	if(chess[x+1][y]==0 && x+1<=m)
		DFS(x+1,y);
	if(chess[x][y+1]==0 && y+1<=n)
		DFS(x,y+1);
	chess[x][y]=0;	
}

int main()
{
    while(scanf("%d%d",&n,&m) != EOF)
    {
        DFS(0,0);
        printf("%d\n",sum);
        sum =0;
        memset(chess,0,sizeof(chess));
    }
    return 0;
}

发表于 2020-04-14 23:13:29 回复(0)
这题的输入是坑呐~~~
明明说的输入两行,结果确是一行用空格隔开。。。
输出需要说明的是:需要它能够持续跑完所有的测试用例,也就是说需要一次输入一次输出,然后继续接受参数,继续输出,以此类推
发表于 2020-03-30 23:12:50 回复(0)
import java.util.*;

public class Main{
    public static void main(String[] args){
        Scanner sc=new Scanner(System.in);
        while(sc.hasNextInt()){
            int m=sc.nextInt();
            int n=sc.nextInt();
            int t=m+n;
            int s=m>n?n:m;
            System.out.println(cal(t,s));
        }
    }
    public static int cal(int i,int j){
        if(j==0) return i;
        int a=1,b=1;
        for(int z=0;z<j;z++){
            a*=i-z;
            b*=z+1;
        }
        return a/b;
    }
}

发表于 2020-03-03 17:39:09 回复(0)
//可以用递归解决,但是最后的函数出口应该是n = 1或者m = 1的情况
//另外可以用动态规划方法解决(如下) #include<iostream> using namespace std; int main(){     int n = 0, m = 0;     while(cin>>n, cin>>m){         int dp[n+1][m+1];         for(int i =0;i<n+1;i++){             for(int j = 0;j<m+1;j++){                 if(i == 0 && j == 0){                     dp[i][j]= 1;                 }else if(i == 0 && j != 0){                     dp[i][j] = dp[i][j-1];                 }else if(i != 0 && j == 0){                     dp[i][j] = dp[i-1][j];                 }else{                     dp[i][j] = dp[i][j-1] + dp[i-1][j];                 }             }         }         cout<<dp[n][m]<<endl;     }     return 0; }
发表于 2020-03-02 12:28:32 回复(0)
def walk(n,m):
    if n==0&nbs***bsp;m==0:
        return 1
    return walk(n-1,m)+walk(n,m-1)

while True:
    try:
        l=input().split()
        n=int(l[0])
        m=int(l[1])
        print(walk(n,m))
    except:
        break

用递归去做,通项公式为:f(n,m)=f(n-1,m)+f(n,m-1),假设终点坐标为(n,m)。边界条件:当n==1或者m==1时,只有1种走法。
发表于 2020-02-21 16:28:44 回复(0)
while True:
    try:
        a,b = map(int, raw_input().split())
        a += 1
        b += 1
        #b = int(raw_input())
        dp = [[0]*(b+1) for _ in range(a+1)]
        dp[0][1] = 1
        for i in range(1,a+1):
            for j in range(1,b+1):
                dp[i][j] = dp[i-1][j]+dp[i][j-1]
        print dp[-1][-1]
    except:
        break
发表于 2019-07-16 15:53:47 回复(0)
动态规划   且额外空间O(min(m,n))
int numofstep(int max, int min)
{
    if (max < min)
        swap(max, min);
    vector<int> arr(min+1, 1);
    for (int i = 1; i <= max; ++i)
        for (int j = 1; j <= min;++j)
            arr[j] = arr[j] + arr[j - 1];
    return arr[min];
}
int main()
{
    int m, n;
    while (cin >> m >> n)
        cout << numofstep(m, n) << endl;
    return 0;
}

发表于 2019-07-11 15:13:34 回复(0)
#include <bits/stdc++.h>
 using namespace std;
//void dfs()
 int main()
 {
     int n,m;
     while(cin>>n>>m)
     {
         vector<vector<int> > dp(m+1,vector<int>(n+1,0));
         dp[0][0]=1;
         for(int i=1;i<n+1;i++)
             dp[0][i]=1;
         for(int j=1;j<m+1;j++)
             dp[j][0]=1;
         for(int i=1;i<m+1;i++)
         {
             for(int j=1;j<n+1;j++)
             {
                 dp[i][j] = dp[i-1][j]+dp[i][j-1];
             }
         }
         int res = dp[m][n];
         cout<<res<<endl;
     }
         system("pause");
         return 0;
 }

发表于 2018-08-06 13:01:52 回复(0)