#include <iostream>
#include <stdio.h>
using namespace std;
/*
问题:设想有个机器人坐在X*Y网格的左上角,只能向右、向下移动。机器人从(0,0)到(X,Y)有多少种走法?
进阶:假设有些点为“禁区”,机器人不能踏足。设计一种算法,找出一条路径,让机器人从左上角移动到右下角。
分析:逆推,设f(x,y)表示从(0,0)到(x,y)所有走法,那么f(x,y) = f(x-1,y) + f(x,y-1)
发现f(x,0)=1,f(0,y)=1
所以递推方程为
{f(x-1,y)+f(x,y-1)
f(x,y)={1 , x=0或y=0
输入:
2(x) 2(y)
3 4
0 1
输出:
6
35
1
关键:
1 逆推,设f(x,y)表示从(0,0)到(x,y)所有走法,那么f(x,y) = f(x-1,y) + f(x,y-1)
发现f(x,0)=1,f(0,y)=1
所以递推方程为
{f(x-1,y)+f(x,y-1)
f(x,y)={1 , x=0或y=0
2 相当于从X+Y步中从中选择X步为向右移动,所以为
(X+Y) = (X+Y)! / (X! * Y!)
(X )
厉害,没想到用排列组合来做,就是从整体中挑选出部分按照题目设定的跳进进行处理
*/
int countPaths(int** pArr , int x , int y)
{
if(NULL == pArr)
{
return -1;
}
if(x < 0 || y < 0)
{
return 0;
}
if( *(pArr[x] + y) != -1 )
{
return *(pArr[x] + y);
}
if( 0 == x)
{
return pArr[x][y] = 1;
}
if( 0 == y )
{
return pArr[x][y] = 1;
}
pArr[x][y] = countPaths(pArr ,x-1 ,y) + countPaths(pArr , x ,y-1);
return pArr[x][y];
}
void process()
{
int x , y;
while(cin >> x >> y)
{
if(x < 0 || y < 0)
{
cout << "x,y is false ,input again" << endl;
continue;
}
//实例化一个二维数组,需要用二维指针和指针数组,int* [10]表示是一个指针数组,数组中每个元素是一个指针,指向含有10个元素的数组
int** pArr = new int* [y+1];
for(int i = 0 ; i <= x ; i++ )
{
pArr[i] = new int[y+1];
//初始化每个数组元素的值为-1
memset(pArr[i] , -1 , sizeof(pArr[i]) * (y+1));
}
//接下来开始计算
int result = countPaths(pArr , x , y);
cout << result << endl;
//释放空间
for(int i = 0 ; i <= x ; i++ )
{
delete[] pArr[i];
}
delete[] pArr;
}
}
int main(int argc , char* argv[])
{
process();
getchar();
return 0;
}