알고리즘/백준

18430번 - 무기 공학

fleur75 2023. 7. 19. 14:14

1️⃣ 완전 탐색(DFS)

 

✏️ 풀이 과정

N, M이 5까지로 굉장히 칸 수가 적은 편이기 때문에 완전 탐색을 요구하는 것을 추측해볼 수 있습니다. 문제는 부메랑 모양을 놓은 후에 빈 칸은 어떻게 처리해야 하는지, 부메랑을 놓은 상태를 어떻게 유지할지가 굉장히 어렵게 느껴진다는 것입니다.

 

이에 대한 해결방법은 DFS에서 방문 표시를 취소함으로써 구현할 수 있는 모든 경로 탐색을 이용하되 중심을 기준으로 삼아 N*M개의 칸을 탐색하는 것입니다. 즉 각 칸을 중심으로 삼아서 가능한 4개의 부메랑 모양이 가능한지 여부를 테스트하고 가능할 경우 해당 세 칸에 방문 표시 후 중심을 다음 칸(열에서 오른쪽으로 한 칸, 끝 열일 경우 다음 행의 처음)으로 이동해서 반복하는 것입니다.

 

이렇게 하면 가능한 모든 경우의 수를 셀 수 있습니다. 합계를 파라미터로 계속 들고다니면서 더하다가 마지막 행이 끝나고 행의 인덱스가 N이 되었을 때 max값을 갱신해주면 됩니다.

 

⏱ 시간 복잡도

각 칸마다 4개의 분기가 생길 수 있기 때문에 시간 복잡도는 O(4^(N*M))이 됩니다. 지수적으로 증가해서 매우 무거운 로직이지만 N과 M이 총 5개까지만 가능하고 실제로는 방문 표시 때문에 칸마다의 분기의 평균은 2개도 되지 않을 것으로 예상됩니다. 2^25가 33554432이기 때문에 대략적으로 시간 내에 해결될 것을 추측해볼 수 있습니다.

 

💻 코드

JavaScript

const input = require("fs")
    .readFileSync(process.platform === "linux" ? "/dev/stdin" : "input.txt")
    .toString()
    .trim()
    .split("\n");

const [N, M] = input[0].split(" ").map(Number);
const map = Array.from(Array(N), (_, i) => input[i + 1].split(" ").map(Number));
const visited = Array.from(Array(N), () => Array(M));
let max = -Infinity;

const dfs = (r, c, sum) => {
    if (r == N) {
        if (sum > max) {
            max = sum;
        }
        return;
    }
    if (!visited[r][c]) {
        if (r - 1 >= 0 && !visited[r - 1][c]) {
            if (c - 1 >= 0 && !visited[r][c - 1]) {
                visited[r][c] = true;
                visited[r - 1][c] = true;
                visited[r][c - 1] = true;
                if (c != M - 1) {
                    dfs(
                        r,
                        c + 1,
                        sum + 2 * map[r][c] + map[r - 1][c] + map[r][c - 1]
                    );
                } else {
                    dfs(
                        r + 1,
                        0,
                        sum + 2 * map[r][c] + map[r - 1][c] + map[r][c - 1]
                    );
                }
                visited[r][c] = false;
                visited[r - 1][c] = false;
                visited[r][c - 1] = false;
            }
            if (c + 1 < M && !visited[r][c + 1]) {
                visited[r][c] = true;
                visited[r - 1][c] = true;
                visited[r][c + 1] = true;
                if (c != M - 1) {
                    dfs(
                        r,
                        c + 1,
                        sum + 2 * map[r][c] + map[r - 1][c] + map[r][c + 1]
                    );
                } else {
                    dfs(
                        r + 1,
                        0,
                        sum + 2 * map[r][c] + map[r - 1][c] + map[r][c + 1]
                    );
                }
                visited[r][c] = false;
                visited[r - 1][c] = false;
                visited[r][c + 1] = false;
            }
        }
        if (r + 1 < N && !visited[r + 1][c]) {
            if (c - 1 >= 0 && !visited[r][c - 1]) {
                visited[r][c] = true;
                visited[r + 1][c] = true;
                visited[r][c - 1] = true;
                if (c != M - 1) {
                    dfs(
                        r,
                        c + 1,
                        sum + 2 * map[r][c] + map[r + 1][c] + map[r][c - 1]
                    );
                } else {
                    dfs(
                        r + 1,
                        0,
                        sum + 2 * map[r][c] + map[r + 1][c] + map[r][c - 1]
                    );
                }
                visited[r][c] = false;
                visited[r + 1][c] = false;
                visited[r][c - 1] = false;
            }
            if (c + 1 < M && !visited[r][c + 1]) {
                visited[r][c] = true;
                visited[r + 1][c] = true;
                visited[r][c + 1] = true;
                if (c != M - 1) {
                    dfs(
                        r,
                        c + 1,
                        sum + 2 * map[r][c] + map[r + 1][c] + map[r][c + 1]
                    );
                } else {
                    dfs(
                        r + 1,
                        0,
                        sum + 2 * map[r][c] + map[r + 1][c] + map[r][c + 1]
                    );
                }
                visited[r][c] = false;
                visited[r + 1][c] = false;
                visited[r][c + 1] = false;
            }
        }
    }

    if (c != M - 1) {
        dfs(r, c + 1, sum);
    } else {
        dfs(r + 1, 0, sum);
    }
};

dfs(0, 0, 0);
console.log(max);