剑指 Offer 13. 机器人的运动范围
题目:地上有一个m行n列的方格,从坐标 [0,0] 到坐标 [m-1,n-1] 。一个机器人从坐标 [0, 0] 的格子开始移动,它每次可以向左、右、上、下移动一格(不能移动到方格外),也不能进入行坐标和列坐标的数位之和大于k的格子。例如,当k为18时,机器人能够进入方格 [35, 37] ,因为3+5+3+7=18。但它不能进入方格 [35, 38],因为3+5+3+8=19。请问该机器人能够到达多少个格子?
题目链接:https://leetcode-cn.com/problems/ji-qi-ren-de-yun-dong-fan-wei-lcof/
方法一:图的广度优先遍历:
思路:
由题干可知机器人只能够上下左右移动,这说明可能有些区域能够满足小于k但是机器人本身无法到达该区域。(大部分的可行区间集中于数组的左半边),所以通过数组遍历的方法不能够有效的判断哪些区域是机器人不可达的,所以考虑使用广度优先遍历算法进行求解。
实现代码如下:
public static int movingCount(int m, int n, int k) {
int[] dx= {0,0,1,-1};
int[] dy= {1,-1,0,0};
int res=0;
Queue<int[]> que =new ArrayDeque<>();
int[][] area=new int[m][n];
area[0][0]=0;
que.offer(new int[] {0,0});
int[] point=null;
while(!que.isEmpty()) {
point=que.poll();
int x=point[0],y=point[1];
if(count(x,y,k)) {
if((x<m&&y<n) &&area[x][y]!=1) {
res++;
area[x][y]=1;
}
}
for(int i=0;i<4;i++) {
int newX=x+dx[i];
int newY=y+dy[i];
if(newX<0||newY<0||newX>m||newY>n||area[newX][newY]==1)continue;
if(count(newX,newY,k)) {
area[newX][newY]=1;
res++;
que.offer(new int[] {newX,newY});
}
}
}
return res;
}
public static boolean count(int num,int mun,int k) {
int res=0;
while(num/10!=0) {
res+=num%10;
num/=10;
}
while(mun/10!=0) {
res+=mun%10;
mun/=10;
}
res+=num;
res+=mun;
if(res>k)return false;
return true;
}
图的广度优先遍历模板:
我理解的广度优先遍历算法大概分为:方向数组、双端链表(ArrayDeque)、循环体(完成图的功能要求)、图的更新(处理过的值进行标记)四个部分。
方向数组:
根据题目要求来设计方向数组。
//上下左右:
int[] dx= {0,0,1,-1};
int[] dy= {1,-1,0,0};
//四周
int[] dx= {-1,-1,-1,0,0,1,1,1};
int[] dy= {-1,0,1,-1,1,-1,0,1};
具体情况根据实际情况考虑。可能也会有各种各样的情况(三维、定向)。
双端链表
采用双端链表来进行循环。
采用双端链表的目的:其实本质上是需要的是一个前出后进的队列。
//定义
Queue<int[]> que =new ArrayDeque<>();
//存入
que.offer(new int[]{0,0});
//取出
int[] point=que.poll();
//判断为空
que.isEmpty();
循环体和更新数组
具体情况具体分析单独讲没什么参考性。