PS

[BOJ 12869] 뮤탈리스크 (Java)

기맹기 2022. 9. 11. 01:56

BOJ 12869 뮤탈리스크

난이도 : 골드 4

https://www.acmicpc.net/problem/12869

 

12869번: 뮤탈리스크

1, 3, 2 순서대로 공격을 하면, 남은 체력은 (12-9, 10-1, 4-3) = (3, 9, 1)이다. 2, 1, 3 순서대로 공격을 하면, 남은 체력은 (0, 0, 0)이다.

www.acmicpc.net

 

전략

처음에는 hp가 많이 남은 순으로 9, 3, 1을 배정해서 그리디로 풀 수 있을까 고민했다.

 

하지만 12, 9, 3 같은 경우를 생각해보면

12, 9, 3 -> 3, 6, 2 -> 0, 0, 1 -> 0, 0, 0 으로 3번이 되는데 최적의 방법은

12, 9, 3 -> 9, 0, 2 -> 0, 0, 0 으로 2번만에 가능한 것을 볼수 있다.

 

즉 경우의 수를 탐색해봐야 하므로 dp로 전략을 세워야한다.

scv는 1 ~ 3개이지만 dp 배열은 항상 3개로 고정시키고 scv가 3개 미만일 경우에는 처음부터 hp를 0으로 설정하면 된다.

 

-9, -3, -1을 배치하는 3! = 6개의 경우의 수를 dfs로 탐색하면서 메모이제이션을 활용해 중복된 연산을 제거할 수 있다.

 

나는 추가로 3개의 hp의 위치가 바뀌어도 같은 결과를 의미하기 때문에 더 높은 효율을 끌어낼 수 있도록 dp를 더 활용해보았다.

 

시행착오

사실 이 문제 풀면서 분명 맞는데 왜 자꾸 틀리지.. 했는데 한 군데에 오타가 있었다.. (hp 로컬 변수 이름에서)

 

한 번 크게 혼났으니까 다음부턴 더 신경쓰면서 할 것 같다.

 

코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Main {

    static int[][][] dp;

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int N = Integer.parseInt(br.readLine());
        int[] hp = new int[3];
        String[] line = br.readLine().split(" ");
        for (int i = 0; i < N; i++)
            hp[i] = Integer.parseInt(line[i]);

        dp = new int[61][61][61];
        for (int i = 0; i < dp.length; i++)
            for (int j = 0; j < dp[i].length; j++)
                for (int k = 0; k < dp[j].length; k++)
                    dp[i][j][k] = Integer.MAX_VALUE;
        dp[0][0][0] = 0;

        System.out.println(solution(hp[0], hp[1], hp[2]));
    }

    static int solution(int hp1, int hp2, int hp3) {
        hp1 = Math.max(hp1, 0);
        hp2 = Math.max(hp2, 0);
        hp3 = Math.max(hp3, 0);

        if (dp[hp1][hp2][hp3] != Integer.MAX_VALUE)
            return dp[hp1][hp2][hp3];
        if (dp[hp1][hp3][hp2] != Integer.MAX_VALUE)
            return dp[hp1][hp2][hp3] = dp[hp1][hp3][hp2];
        if (dp[hp2][hp1][hp3] != Integer.MAX_VALUE)
            return dp[hp1][hp2][hp3] = dp[hp2][hp1][hp3];
        if (dp[hp2][hp3][hp1] != Integer.MAX_VALUE)
            return dp[hp1][hp2][hp3] = dp[hp2][hp3][hp1];
        if (dp[hp3][hp1][hp2] != Integer.MAX_VALUE)
            return dp[hp1][hp2][hp3] = dp[hp3][hp1][hp2];
        if (dp[hp3][hp2][hp1] != Integer.MAX_VALUE)
            return dp[hp1][hp2][hp3] = dp[hp3][hp2][hp1];

        dp[hp1][hp2][hp3] = Math.min(dp[hp1][hp2][hp3], solution(hp1 - 9, hp2 - 3, hp3 - 1) + 1);
        dp[hp1][hp2][hp3] = Math.min(dp[hp1][hp2][hp3], solution(hp1 - 9, hp2 - 1, hp3 - 3) + 1);
        dp[hp1][hp2][hp3] = Math.min(dp[hp1][hp2][hp3], solution(hp1 - 3, hp2 - 9, hp3 - 1) + 1);
        dp[hp1][hp2][hp3] = Math.min(dp[hp1][hp2][hp3], solution(hp1 - 3, hp2 - 1, hp3 - 9) + 1);
        dp[hp1][hp2][hp3] = Math.min(dp[hp1][hp2][hp3], solution(hp1 - 1, hp2 - 9, hp3 - 3) + 1);
        dp[hp1][hp2][hp3] = Math.min(dp[hp1][hp2][hp3], solution(hp1 - 1, hp2 - 3, hp3 - 9) + 1);

        return dp[hp1][hp2][hp3];
    }
}

 

깨달은 점

간단한 dp문제라서 자신감을 얻기 좋은 것 같다.