前言

代码的出现 已经过到第六天啦,这关逐渐有意思起来了,这里记录一下我的解法,当然不是最优的解法,第一时间能想到的且最笨的解法。

守卫加里凡特

这天的名字叫 Guard Gallivant,要算出守卫在地图中走过的面积,地图如下:

....#.....
.........#
..........
..#.......
.......#..
..........
.#..^.....
........#.
#.........
......#...

守卫一开始是朝着箭头的方向开始走,只要遇到 # 就往顺时针旋转 90° 的方向继续走,直到走出地图。

解题

矩阵里查找线路,我们很容易想到可以使用深度优先遍历,而且递归的写法更清晰明了,所以一开始我就决定用递归深度优先来解。

当遇到 # 就顺时针旋转 90°,我们可以先定义一个字典来存一下,遇到 # 要转变的下一个方向

const transformPosMap = {
    'up': 'right',
    'right': 'down',
    'down': 'left',
    'left': 'up'
}

然后我们开始定义递归函数 dfs,我们用一个 visited 数组来记录守卫走过的路,走过的置为 1,最后我们计算一下 visited 里的 1 的数量就得出这题的答案。

const dfs = (i, j, visited, matrix, rows, cols, pos) => {
    if (i >= rows || i < 0 || j >= cols || j < 0) return;
    if (visited[i][j] === 0) {
        visited[i][j] = 1;
    };

    if (pos === 'up') {
        if (matrix[i - 1] && matrix[i - 1][j] === '#') {
            return dfs(i, j + 1, visited, matrix, rows, cols, transformPosMap[pos]);
        } else {
            return dfs(i - 1, j, visited, matrix, rows, cols, pos);
        }
    } else if (pos === 'right') {
        if (matrix[i][j + 1] === '#') {
            return dfs(i + 1, j, visited, matrix, rows, cols, transformPosMap[pos]);
        } else {
            return dfs(i, j + 1, visited, matrix, rows, cols, pos);
        }
    } else if (pos === 'down') {
        if (matrix[i + 1] && matrix[i + 1][j] === '#') {
            return dfs(i, j - 1, visited, matrix, rows, cols, transformPosMap[pos]);
        } else {
            return dfs(i + 1, j, visited, matrix, rows, cols, pos);
        }
    } else if (pos === 'left') {
        if (matrix[i][j - 1] === '#') {
            return dfs(i - 1, j, visited, matrix, rows, cols, transformPosMap[pos]);
        } else {
            return dfs(i, j - 1, visited, matrix, rows, cols, pos);
        }
    }
}

dfs 函数写出来就简单了,我们先找到入口坐标, 记在变量 oi,oj 上,然后调用 dfs 函数,最后遍历 visited 二维数组里 1 的数量就大功告成啦

for (let i = 0; i < matrix.length; i++) {
        let find = false;
        for (let j = 0; j < matrix[i].length; j++) {
            if (matrix[i][j] === '^') {
                oi = i;
                oj = j;
                find = true;
                break;
            }
        }
        if (find) break;
    }
    dfs(oi, oj, visited, matrix, rows, cols, 'up');
    let ans = 0;
    for (let i = 0; i < visited.length; i++) {
        for (let j = 0; j < visited[i].length; ++j) {
            if (visited[i][j] === 1) {
                ans++;
            }
        }
    }
    return ans;

大功告成过早了,示例完美运行,谜题输入爆栈了,悲催。

不过递归已经写出来了,整体思路示对的,我们把递归改为循环就可以了

    let i = oi;
    let j = oj;
    let pos = 'up';
    while (i < rows && i >= 0 && j < cols && j >= 0) {
        console.log('i: ', i, 'j: ', j, 'pos: ', pos)
        if (visited[i][j] === 0) {
            visited[i][j] = 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--;
            }
        }
    }

谜题输入一跑,这次是真的大功告成!

part two 待续。。。