程序员面试金典: 9.9 递归和动态规划 9.2机器人走路的方式

#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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值