패션왕 신해빈

구해야 하는 것

  • 해빈이가 옷을 하나라도 입은 상태로 며칠 동안 밖에 돌아다닐 수 있는지 구하라

주어진 자료

  • 테스트 케이스 <= 100
  • 0 <= 해빈이가 가진 의상 수 n <= 30
  • 1 <= 모든 문자열 길이 <= 20
  • 중복된 의상 이름은 주어지지 않는다.

조건

  • 같은 종류의 의상은 하나만 입을 수 있다.
  • 한 조합은 두번 다시 입지 않는다.

계획

  1. 테스트 케이스를 입력받는다.
  2. n을 입력받는다.
  3. 의상 종류를 key로, 개수를 value로 갖는 맵을 만든다.
  4. 만약 맵이 아래와 같이 만들어졌다면,
    {
     "headgear":2,
     "eyewear":1
    }
    

    모든 경우의 수는 (2C1 + headgear를 모두 선택하지 않는 경우) * (1C1 + eyewear를 모두 선택하지 않는 경우) - (아무것도 입지 않는 경우)
    즉, (2C1 + 1) * (1C1 + 1) - 1

실행

public class Main {
    HashMap<String, Integer> map;

    // 의상을 입을 수 있는 모든 경우의 수 세기
    public int countAllCases() {
        int cnt = 1;

        for(int val : map.values()) {
            cnt *= (val + 1); // val = 옷을 각각 하나씩 선택하는 경우의 수, 1 = 한 종류를 전부 선택하지 않는 경우의 수
        }
        cnt -= 1; // 아무 종류도 선택하지 않는 경우 빼줌

        return cnt;
    }

    public void solution() throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int testCase = Integer.parseInt(br.readLine()); // 테스트 케이스 입력

        for(int i = 0; i < testCase; i++) {
            map = new HashMap<>();

            int n = Integer.parseInt(br.readLine()); // n 입력

            for(int j = 0; j < n; j++) {
                StringTokenizer st = new StringTokenizer(br.readLine(), " ");
                String name = st.nextToken(); // (의상 이름은 필요 없음)
                String key = st.nextToken();

                // 맵에 특정 종류에 대한 옷 개수를 넣어줌
                if(map.get(key) == null) {
                    map.put(key, 1);
                } else {
                    map.put(key, map.get(key) + 1);
                }
            }

            int answer = countAllCases(); // 모든 경우의 수 세기
            System.out.println(answer);
        }
    }

    public static void main(String[] args) throws IOException {
        new Main().solution();
    }
}

반성

  • 모든 경우의 수를 세는 공식을 구하는 것이 관건인 문제였다.
    처음에는 아래와 같이 접근했었다.
    1. 옷 종류 중 1개를 선택하는 경우
      headgear 선택 → headgear의 value에서 1개를 선택하는 경우(2C1)
      eyewear 선택 → eyewear의 value에서 1개를 선택하는 경우(1C1)
    2. 옷 종류 중 2개를 선택하는 경우
      headgear, eyewear 선택 → headgear의 value에서 1개를 선택하는 경우 * eyewear의 value에서 1개를 선택하는 경우(2C1 * 1C1)

    → 2C1 + 1C1 + (2C1 * 1C1) = 2 + 1 + 2 = 5

    이걸 단순하게 바꾸면 아래와 같이 된다.
    (headgear 옷들 중 1개를 고르는 경우 + headgear를 아예 선택하지 않는 경우) * (eyewear 옷들 중 1개를 고르는 경우 + eyewear를 아예 선택하지 않는 경우) - (아무것도 입지 않는 경우)

    처음 접근법도 틀린건 아니지만, 거기에만 매몰돼서 '이 복잡한걸 어떻게 구현하지?' 라는 생각에 막막했던 것 같다. 복잡한 문제를 마주하면 이를 단순하게 바꿔보자!