面试题13:机器人的运动范围
// 面试题13:机器人的运动范围
// 题目:地上有一个m行n列的方格。一个机器人从坐标(0, 0)的格子开始移动,它
// 每一次可以向左、右、上、下移动一格,但不能进入行坐标和列坐标的数位之和
// 大于k的格子。例如,当k为18时,机器人能够进入方格(35, 37),因为3+5+3+7=18。
// 但它不能进入方格(35, 38),因为3+5+3+8=19。请问该机器人能够到达多少个格子?
解题思路:
还是和面试题12一样的回溯算法,只不过这个比12题简单多了。
这里明面给出的限制条件只有一个,就是格子的各位之和不可以超过某个给定的数值。
首先准备进入0行0列,当准备进入i行j列的时候,先进行条件的判断,
如果条件符合,就进去,然后上下左右继续尝试,直到尝试到最后一个格子。
其实有一个隐含的条件,就是不可以两次重复进入一个格子,
所以这次我们同样需要一个bool类型的数组来记录是否已经选中了某个格子。
什么?你问那些不符合条件而没被选中的会不会一直遍历下去?
当然不会,条件都不符合,连走的机会都不给他^_^
c/c++:
//计算机器人可以到达格子数
int movingCount(int limitation, int rows, int cols) {
//参数有效性校验
if (limitation < 0 || rows <= 0 || cols <= 0)
return 0;
//初始化标记数组
bool* visited = new bool[rows*cols];
memset(visited, false, rows*cols);
//尝试进入0行0列的格子
int count = movingCountCore(limitation, rows, cols, 0, 0, visited);
//释放内存并返回
delete[] visited;
return count;
}
//回溯算法核心
int movingCountCore(int limitation, int rows, int cols, int row, int col, bool* visited) {
int count = 0;
//可以进入当前的格子
if (check(limitation, rows, cols, row, col, visited)) {
//标记格子已经走过
visited[row*cols + col] = true;
//尝试向上下左右走出一步
count = 1 + movingCountCore(limitation, rows, cols, row, col - 1, visited)
+ movingCountCore(limitation, rows, cols, row, col + 1, visited)
+ movingCountCore(limitation, rows, cols, row - 1, col, visited)
+ movingCountCore(limitation, rows, cols, row + 1, col, visited);
}
return count;
}
//校验是否可以进入某个格子
bool check(int limitation, int rows, int cols, int row, int col, bool* visited) {
//行列合法,符合限制条件,且未走过
if (row >= 0 && row < rows&&col >= 0 && col < cols && !visited[row*cols + col] &&
getSum(row) + getSum(col) <= limitation)
return true;
return false;
}
//计算某个数字各位之和
int getSum(int number) {
int sum = 0;
while (number > 0) {
sum += number % 10;
number /= 10;
}
return sum;
}