剑指offer_机器人的运动范围

/*
机器人的运动范围:
地上有一个m行和n列的方格。
一个机器人从坐标0,0的格子开始移动,每一次只能向左,右,上,下四个方向移动一格,但是不能进入行坐标和列坐标的数位之和大于k的格子。 
例如,当k为18时,机器人能够进入方格(35,37),因为3+5+3+7 = 18。
但是,它不能进入方格(35,38),因为3+5+3+8 = 19。请问该机器人能够达到多少个格子?

思路1:
应该是求最多能到达多少格子吧,因为选择的路径不同,可达的格子数也不同
与66题矩阵中的路径比较像,66题是试探性的去尝试一条路径,如果不能匹配字符串,则回溯;本题应该是要遍历所有路径,看哪条路径可达格子最多

剑指offer思路:不是说机器人必须沿着一路径走,只需要关注机器人可以到达的区域

两种思路的结果是一样的

*/

class  MovingCount
{
	static int count;

	public static int movingCount(int threshold, int rows, int cols)
    {
        if (threshold<0||rows<=0||cols<=0)
		{
			return 0;
		}

		//记录方格是否被访问过
        boolean[][] visited=new boolean[rows][cols];
		
		//思路1
        //reachable(0, 0, rows, cols, threshold,visited);

		//剑指offer思路
		count =reachable2(0, 0, rows, cols, threshold,visited);

		return count;
    }

	public static int reachable(int row, int col, int rows, int cols, int threshold, boolean[][] visited)
	{
		if (row<rows&&col<cols)
		{
			//计算行坐标和列坐标的数位之和
			int digitSum=0;
			int digitRow=row;
			int digitCol=col;

			while (digitRow>0)
			{
				digitSum+=digitRow%10;
				digitRow=digitRow/10;
			}
			while (digitCol>0)
			{
				digitSum+=digitCol%10;
				digitCol=digitCol/10;
			}

			//若格子满足要求
			if (digitSum<=threshold)
			{
			
				//更新可达格子数
				count++;
				//标记为已访问
				visited[row][col]=true;
								
				//若当前选定格子的上侧有格子且未被访问过
				if(row-1>=0&&!visited[row-1][col])
				{
					//上侧格子作为下一个选择,最终会得到的最大格子数
					int countUp=reachable(row-1, col, rows, cols, threshold,visited);
					count=countUp;
				}
				
				if(row+1<rows&&!visited[row+1][col])
				{
					int countDown=reachable(row+1, col, rows, cols, threshold,visited);
					if (countDown>count)
					{
						count=countDown;
					}
				}
				
				if(col-1>=0&&!visited[row][col-1])
				{
					int countLeft=reachable(row, col-1, rows, cols, threshold,visited);
					if (countLeft>count)
					{
						count=countLeft;
					}
				}
				
				if(col+1<cols&&!visited[row][col+1])
				{
					int countRight=reachable(row, col+1, rows, cols, threshold,visited);
					
					if (countRight>count)
					{
						count=countRight;
					}
				}
			
			}
		}

		return count;
	}

	public static int reachable2(int row, int col, int rows, int cols, int threshold, boolean[][] visited)
	{
		int count2=0;
		if (row>=0&&row<rows&&col>=0&&col<cols&&!visited[row][col])
		{
			//计算行坐标和列坐标的数位之和
			int digitSum=0;
			int digitRow=row;
			int digitCol=col;

			while (digitRow>0)
			{
				digitSum+=digitRow%10;
				digitRow=digitRow/10;
			}
			while (digitCol>0)
			{
				digitSum+=digitCol%10;
				digitCol=digitCol/10;
			}

			//若格子满足要求
			if (digitSum<=threshold)
			{
				//标记为已访问
				visited[row][col]=true;
				
				//向四周扩展区搜寻可以到达的格子
				count2=1+reachable2(row-1, col, rows, cols, threshold,visited)+
				reachable2(row+1, col, rows, cols, threshold,visited)+
				reachable2(row, col-1, rows, cols, threshold,visited)+
				reachable2(row, col+1, rows, cols, threshold,visited);	
			}
		}

		return count2;
	}

	public static void main(String[] args) 
	{
		System.out.println(movingCount(15,20,20));
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值