机器人的运动范围
机器人的运动范围
http://www.nowcoder.com/questionTerminal/6e5207314b5241fb83f2329e89fdecc8
个人想法,有错误请批!
题目描述
地上有一个m行和n列的方格。一个机器人从坐标0,0的格子开始移动,每一次只能向左,右,上,下四个方向移动一格,但是不能进入行坐标和列坐标的数位之和大于k的格子。 例如,当k为18时,机器人能够进入方格(35,37),因为3+5+3+7 = 18。但是,它不能进入方格(35,38),因为3+5+3+8 = 19。请问该机器人能够达到多少个格子?
思路
这道题我先是用BFS(广搜)的思路去解决的,BFS一般是用来查找源点到目的结点之间的最短路径,它的实现思路是通过一个点往外扩散,然后外层点再往外扩散,一直持续下去,直到碰到目的结点,那么扩散的层次一定是最小的,可以幻想成一颗石头丢进水里,水的波纹不停往外扩,而这道题可以利用bfs扩散的特点,不停往外扩散,记录扩散走过的格子数,直到不能扩为止,答案就over了。
至于DFS(深搜)的思路,也是可以解决的,就是一路走到黑,走到死胡同再退回一步,从另一个方向一路走到黑,重复以上过程,直到全部可走方格都走完为止。可以递归、可以非递归(用栈实现)
代码实现
递归版本实现DFS
/**
* 递归版本实现dfs
* @param threshold
* @param rows
* @param cols
* @return
*/
public int movingCount2(int threshold, int rows, int cols) {
if (threshold < 0 || rows <= 0 || cols <= 0)
return 0;
boolean[][] visited = new boolean[rows][cols];
return dfs(threshold, 0, 0, rows, cols, visited);
}
private int dfs(int threshold, int x, int y, int rows, int cols, boolean[][] visited) {
//先判断当前结点是否可以走
if(judge(x,y, visited, rows,cols, threshold)){
visited[x][y] = true;
//获取从(x,y)四个方位出发,可以走的路径长度
return 1 + dfs(threshold, x -1, y, rows, cols, visited) + //上
dfs(threshold, x , y + 1, rows, cols, visited) + //右
dfs(threshold, x +1, y, rows, cols, visited) +//下
dfs(threshold, x , y - 1, rows, cols, visited);//左
}else {
//以当前结点不能进行扩散,则路径长度为0
return 0;
}
}
/**
* 判断(x,y)方块是否可以走
*
* @param x
* @param y
* @param visited
* @param rows
* @param cols
* @return
*/
private boolean judge(int x, int y, boolean[][] visited, int rows, int cols, int threshold) {
//getSum(x, y) > threshold判断位数和是否符合条件
if (x < 0 || x >= rows || y < 0 || y >= cols || visited[x][y] == true || getSum(x, y) > threshold)
return false;
else
return true;
}
private int getSum(int x, int y) {
//获取x,y坐标的位数和
int sum = 0;
while (x % 10 != 0) {
sum += x % 10;
x = x / 10;
}
while (y % 10 != 0) {
sum += y % 10;
y = y / 10;
}
return sum;
}BFS版本,使用队列保存走过的点
public int movingCount(int threshold, int rows, int cols) {
if (threshold < 0 || rows <= 0 || cols <= 0)
return 0;
boolean[][] visited = new boolean[rows][cols];
ArrayList<Integer> paths = new ArrayList<>();
int count = 0;
//将(0,0)结点进队
paths.add(0);
count++;
visited[0][0] = true;
while (paths.size() > 0) {
//取出队首
int heap = paths.remove(0);
//找出上下左右四个可以走过的方块
//heap一维坐标先转成二维坐标
int x = heap / cols;
int y = heap % cols;
int x1 = 0, y1 = 0;//下一个方块的坐标
int dict = 0;
while (dict <= 3) {
switch (dict) {
case 0:
x1 = x - 1;
y1 = y;
break;
case 1:
x1 = x;
y1 = y + 1;
break;
case 2:
x1 = x + 1;
y1 = y;
break;
case 3:
x1 = x;
y1 = y - 1;
break;
}
if (judge(x1, y1, visited, rows, cols, threshold)) {
//当前方块可以走,进队
count++;
visited[x1][y1] = true;
paths.add(x1 * cols + y1);
}
dict++;
}
}
return count;
}
/**
* 判断(x,y)方块是否可以走
*
* @param x
* @param y
* @param visited
* @param rows
* @param cols
* @return
*/
private boolean judge(int x, int y, boolean[][] visited, int rows, int cols, int threshold) {
//getSum(x, y) > threshold判断位数和是否符合条件
if (x < 0 || x >= rows || y < 0 || y >= cols || visited[x][y] == true || getSum(x, y) > threshold)
return false;
else
return true;
}
private int getSum(int x, int y) {
//获取x,y坐标的位数和
int sum = 0;
while (x % 10 != 0) {
sum += x % 10;
x = x / 10;
}
while (y % 10 != 0) {
sum += y % 10;
y = y / 10;
}
return sum;
}
