方格走法总数

  这是一个比较经典得问题,其问题描述如下:给定一个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.csdn.net/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;
}

猜你喜欢

转载自blog.csdn.net/qq_33977775/article/details/80725550