前言
继续来闯关,第二小问还卡了我挺长时间,少了一个小判断。。。
题目
....#.....
....+---+#
....|...|.
..#.|...|.
....|..#|.
....|...|.
.#.O^---+.
........#.
#.........
......#...
这一问是要在地图上放置障碍物,使得守卫进入循环,避免发现我们,比如下面在(6,3)处放置一个障碍物,就会导致守卫循环得走一条路,需要我们找出有多少个位置放上障碍物会导致守卫进入循环。
思路
以前还真没有做过如何判断矩阵中循环路径,一开始没什么思路,后面想到,守卫走过的步数是小于整个矩阵的大小的,如果守卫走的步数巨大,那不就说明守卫进入了循环吗?
根据这个思路我们很快就可以改好第一版代码
解法
我们只需在 while循环中加一个变量来记录守卫走过的步数,当超过一定的数值就退出循环,我这里设置的是矩阵大小的 10 倍。
function checked(matrix, oi, oj) {
const rows = matrix.length;
const cols = matrix[0].length;
let i = oi;
let j = oj;
let pos = 'up';
let step = 0;
while (i < rows && i >= 0 && j < cols && j >= 0) {
step++;
if (step > cols * rows * 10) {
return 1;
}
if (pos === 'up') {
if (matrix[i - 1] && matrix[i - 1][j] === '#') {
j++;
pos = transformPosMap[pos];
} else {
i--;
}
} else if (pos === 'right') {
if (matrix[i][j + 1] === '#') {
i++;
pos = transformPosMap[pos];
} else {
j++;
}
} else if (pos === 'down') {
if (matrix[i + 1] && matrix[i + 1][j] === '#') {
j--;
pos = transformPosMap[pos];
} else {
i++;
}
} else if (pos === 'left') {
if (matrix[i][j - 1] === '#') {
i--;
pos = transformPosMap[pos];
} else {
j--;
}
}
}
return 0;
}
其实我们只需要在守卫走过的路径上放障碍物,可以节省一些判断,因为在守卫没走过的地方放障碍物不会影响到守卫的路径。
let ans = 0;
for (let i = 0; i < rows; i++) {
for (let j = 0; j < cols; ++j) {
if (visited[i][j] === 1 && matrix[i][j] === '.') {
count++;
matrix[i][j] = '#';
if (checked(matrix, oi, oj)) {
ans++;
}
matrix[i][j] = '.';
}
}
}
很遗憾,得出的答案是 1825,比正确答案要高,原因是我们少判断了一种情况
例如上面这种情况,往红色箭头的地方放一个障碍物,当守卫往上走,遇到障碍物的时候,会右转,但是右转也是障碍物,这时就需要再右转 90°,缺少了这个判断。只需要多判断一次就可以了,因为连续右转两次就是 180° 转弯,转回来的路了。
我们改进一下点,多加一个判断,四个方向都要加
function checked(matrix, oi, oj) {
const rows = matrix.length;
const cols = matrix[0].length;
let i = oi;
let j = oj;
let pos = 'up';
let step = 0;
while (i < rows && i >= 0 && j < cols && j >= 0) {
step++;
if (step > cols * rows * 10) {
return 1;
}
if (pos === 'up') {
if (matrix[i - 1] && matrix[i - 1][j] === '#') {
if (matrix[i][j + 1] === '#') {
i++;
pos = revertPosMap[pos];
} else {
j++;
pos = transformPosMap[pos];
}
} else {
i--;
}
} else if (pos === 'right') {
if (matrix[i][j + 1] === '#') {
if (matrix[i + 1] && matrix[i + 1][j] === '#') {
j--;
pos = revertPosMap[pos];
} else {
i++;
pos = transformPosMap[pos];
}
} else {
j++;
}
} else if (pos === 'down') {
if (matrix[i + 1] && matrix[i + 1][j] === '#') {
if (matrix[i][j - 1] === '#') {
i--;
pos = revertPosMap[pos];
} else {
j--;
pos = transformPosMap[pos];
}
} else {
i++;
}
} else if (pos === 'left') {
if (matrix[i][j - 1] === '#') {
if (matrix[i - 1] && matrix[i - 1][j] === '#') {
j++;
pos = revertPosMap[pos];
} else {
i--;
pos = transformPosMap[pos];
}
} else {
j--;
}
}
}
return 0;
}
完美解决
后记
真的想了挺多办法的,卡住的时候挺无奈,没想到是少了一个判断,新的一年已经到来,没有总结的习惯,也没有计划的习惯,看看要不要做个计划吧