这是一个比较经典得问题,其问题描述如下:给定一个M*N的格子或棋盘,求:从左下角走到右上角的走法总数?
(每次只能向右或向上移动一个方格边长的距离)。
对于这个问题,我一开始是通过枚举的方式视图找到规律,当我列举了三四个后发现,走法总数是可以同时向上或向右移动得点减一得二倍(这里只是我以为,其实是错的),我就开始沿着这个思路去做,以下是根据我的思路的写法(这个不是正确的写法,只是想记录一下思维过程)
int getTheResult(int M, int N)
{
int i, j, sum = 0;
if(M == 1){
sum = N + 1;
}else if(N == 1){
sum = M + 1;
}else{
for(i = 0 ; i < M ; i++){
for(j = 0 ; j < N ; j++){
sum++;
}//of for j
}//of for i
}//of if
return sum;
}//of getTheResult
最后测试,确实是我想要的结果,然而找规律最科学的方法是归纳法,简单的枚举有很大的风险,当我把算法写完,再到网上去找答案时,我发现我当N和M都等于3时,结果就不同了,于是我回去检验,发现了自己的错误,当基数足够大时,我的思路其实是不适用的,于是在网上找到了相应正确的解答,我看了一下,这个思路大概可以理解成为抢21点的游戏,我们都知道,当你想抢到21点时,你必须先抢到18点,于是一次类推,递归,于是得到了C语言下递归的解法:
int getSumSteps(int m, int n)
{
if(m <=0 || n<= 0){
return -1;
}
if(m == 1 && n > 0){
return n+1;
}
if(n == 1 && m > 0){
return m+1;
}
// 递归调用
return getSumSteps(m-1, n) + getSumSteps(m, n-1);
//确定递归跳出条件,只关注这一步该做什么,否则将陷入困境,模糊不清
}
说完了递归,我顺便也看了一下非递归,非递归的思路是这样的:你如果想从左下角到右下角,势必会向上走M,向右走N,于是我们索性将它转化成为一个组合问题,就可以得出我们的C语言的非递归解法:
int processNew(int m,int n){
int i, j, res;
int **Q=(int**)malloc(sizeof(int*)*(m+1));
for(i =0; i<=m; ++i){
Q[i]=(int*)malloc(sizeof(int)*(n+1));
}
//初始化
Q[0][0]=0;
for(j=1; j<=n; ++j)
Q[0][j]=1;
for(i=1; i<=m; ++i)
Q[i][0]=1;
//迭代计算
for(i=1; i<=m; ++i){
for(j=1; j<=n; ++j){
Q[i][j]=Q[i-1][j]+Q[i][j-1];
}
}
res=Q[m][n];
return res;
}
后面的解答都是来源https://blog.youkuaiyun.com/hadeso/article/details/12622743,稍微做了一点修改,更多的内容可以参考一下这篇文章里面说得,总的来说,这个问题使用递归的方式比较简单,理解起来也比较容易。
完整代码如下:
#include <stdio.h>
#include <malloc.h>
int getSumSteps(int m, int n)
{
if(m <=0 || n<= 0){
return -1;
}
if(m == 1 && n > 0){
return n+1;
}
if(n == 1 && m > 0){
return m+1;
}
// 递归调用
return getSumSteps(m-1, n) + getSumSteps(m, n-1);
//确定递归跳出条件,只关注这一步该做什么,否则将陷入困境,模糊不清
}
int processNew(int m,int n){
int i, j, res;
int **Q=(int**)malloc(sizeof(int*)*(m+1));
for(i =0; i<=m; ++i){
Q[i]=(int*)malloc(sizeof(int)*(n+1));
}
//初始化
Q[0][0]=0;
for(j=1; j<=n; ++j)
Q[0][j]=1;
for(i=1; i<=m; ++i)
Q[i][0]=1;
//迭代计算
for(i=1; i<=m; ++i){
for(j=1; j<=n; ++j){
Q[i][j]=Q[i-1][j]+Q[i][j-1];
}
}
res=Q[m][n];
return res;
}
int main()
{
int M, N;
printf("请输方格的长(M)和宽(N):\n");
scanf("%d%d",&M, &N);
printf("%d", processNew(M,N));
printf("Hello World!!!\n");
return 0;
}