PS

[BOJ 12969] ABC (Java)

기맹기 2022. 9. 11. 23:54

BOJ 12969 ABC

난이도 : 골드 1

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

 

12969번: ABC

첫째 줄에 문제의 조건을 만족하는 문자열 S를 출력한다. 가능한 S가 여러 가지라면, 아무거나 출력한다. 만약, 그러한 S가 존재하지 않는 경우에는 -1을 출력한다.

www.acmicpc.net

 

전략

 'A'의 개수 a, 'B'의 개수 b로 이루어진 길이가 len인 문자열에서 조건을 만족하는 쌍이 pair만큼 있다면

len + 1 길이의 문자열에서의 pair은 다음과 같다.

1. 'A' 선택 : pair

2. 'B' 선택 : pair + a

3. 'C' 선택 : pair + a + b

 

이전 길이의 문자열에서의 'A', 'B', 'C'의 위치와 관계 없이 개수 a, b에 따라 다음 길이 문자열의 pair이 결정되므로

중복되는 연산을 제거할 수 있다.

 

시행착오

dp에서 항상 특정 상태에서 최적의 값을 저장하다가,

문제의 특이한 구조로 어떻게 저장해야할지 고민이 많이 되었다.

 

처음에는 dp[len][a][b]의 3차원 배열에 int형으로 pair를 저장하려고 했지만

반환 처리를 어떻게 할지 고민하다가 이렇게 구성하였다.

 

코드

import java.util.Scanner;

public class Main {

    static int N, K;
    static char[] seq;
    static boolean[][][][] dp;

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        N = sc.nextInt();
        K = sc.nextInt();

        seq = new char[N + 1];
        dp = new boolean[N + 1][N + 1][N + 1][N * (N - 1) / 2 + 1];

        if (solution(0, 0, 0, 0))
            System.out.println(seq);
        else
            System.out.println(-1);
    }

    static boolean solution(int len, int a, int b, int pairs) {
        if (len == N) {
            if (pairs == K)
                return true;
            return false;
        }

        if (dp[len][a][b][pairs])
            return false;
        dp[len][a][b][pairs] = true;

        seq[len] = 'A';
        if (solution(len + 1, a + 1, b, pairs)) return true;
        seq[len] = 'B';
        if (solution(len + 1, a, b + 1, pairs + a)) return true;
        seq[len] = 'C';
        if (solution(len + 1, a, b, pairs + a + b)) return true;

        return false;
    }

}

 

깨달은 점

메모이제이션으로 중복 연산을 줄이는 방법이 바로바로 떠오를 때까지 열심히 연습해야겠다.