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

#include <iostream>
#include <stdio.h>

using namespace std;

/*
问题:设想有个机器人坐在X*Y网格的左上角,只能向右、向下移动。
      假设有些点为“禁区”,机器人不能踏足。设计一种算法,找出一条路径,让机器人从左上角移动到右下角。
      机器人从(0,0)到(X,Y)有多少种走法?
      
分析:题目的关键就是如何避免走到禁区,一种大的思路是:求出无禁区时的所有路径个数,减去以禁区为起点
      到达终点的路径。这种方式需要考虑,如果存在多个禁区,两个禁区之间之间存在重复的路径,需要排除。
      是否可以在递归中:直接令禁区对应的为0,即可

输入:
3(x) 3(y)
2(禁区个数n,下面有n行,每一行第一个数字是禁区的横坐标,第二个数字是禁区的纵坐标)
1(x坐标) 1(y坐标)
2 2

输出:
4

关键:
1 题目的关键就是如何避免走到禁区,可以在递归中:直接令禁区对应的路径个数为0,即可
2 		//实例化一个二维数组,需要用二维指针和指针数组,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 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;
	int n;
	int xIndex , yIndex;
	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));
		}

		//设置从起点到禁区对应的路径个数为0
		cin >> n;
		for(int k = 0 ; k < n ; k++)
		{
			cin >> xIndex >> yIndex;
			if(xIndex < 0 || yIndex < 0)
			{
				continue;
			}
			pArr[xIndex][yIndex] = 0;
		}

		//接下来开始计算
		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;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值