PS

[백준] 16722번 : 결! 합![Java]

devkdh 2025. 8. 28. 17:21

#풀이

import java.io.*;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.StringTokenizer;


public class Main {
    public static int[][][] isH = new int[10][10][10]; // 합이 아니면 0, 합이면 1, 외쳤으면 2이상 (1이 없으면 결)
    public static boolean checkH(Card a, Card b, Card c){
        Set<String> Sset = new HashSet<String>();
        Set<String> Cset = new HashSet<String>();
        Set<String> Bset = new HashSet<String>();
        //S 체크
        Sset.add(a.S);
        Sset.add(b.S);
        Sset.add(c.S);
        if(Sset.size()==2)return false;
        //C체크
        Cset.add(a.C);
        Cset.add(b.C);
        Cset.add(c.C);
        if(Cset.size()==2)return false;
        //B체크
        Bset.add(a.B);
        Bset.add(b.B);
        Bset.add(c.B);
        return Bset.size() != 2;
    }
    static class Card {
        String S, C, B;

        public Card(String S, String C, String B) {
            this.S = S;
            this.C = C;
            this.B = B;
        }
    }

    public static void main(String[] args) throws IOException {
            BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
            StringTokenizer st;
            int score = 0;
            Card[] cards = new Card[10];
            boolean isG = false;

            for(int i = 1; i<10; i++){
                st = new StringTokenizer(br.readLine());
                cards[i] = new Card(st.nextToken(),st.nextToken(),st.nextToken());
            }
            //합인지 체크
            for(int i = 1; i<10; i++){
                for(int j = i+1; j<10; j++){
                    for(int k = j+1; k<10; k++){
                        if(checkH(cards[i],cards[j],cards[k]))isH[i][j][k] = 1;
                    }
                }
            }
            int n = Integer.parseInt(br.readLine());
            for(int ii = 0; ii<n; ii++){
                boolean flag = true;
                st = new StringTokenizer(br.readLine());
                if(st.nextToken().equals("G")){
                    for(int i = 1; i<10; i++){
                        for(int j = i+1; j<10; j++){
                            for(int k = j+1; k<10; k++){
                                if(isH[i][j][k]==1){
                                    flag = false;
                                    break;
                                }
                            }
                        }
                    }
                    if(flag &&!isG) {
                        score += 3;
                        isG = true;
                    }
                    else score-=1;
                }
                else{
                    int[] arr = new int[3];
                    arr[0] = Integer.parseInt(st.nextToken());
                    arr[1] = Integer.parseInt(st.nextToken());
                    arr[2] = Integer.parseInt(st.nextToken());
                    Arrays.sort(arr);
                    if(isH[arr[0]][arr[1]][arr[2]]==1){
                        score++;
                        isH[arr[0]][arr[1]][arr[2]]++;
                    }
                    else score--;
                }
            }
            System.out.println(score);


          }
}

#성능

#정리

1. 각 줄은 3개의 문자열(S, C, B)로 구성되며, 이를 Card 객체로 만들어 cards[1..9] 배열에 저장한다.

 

2. 9장의 카드 중에서 i < j < k인 모든 3장 조합을 만들고 checkH() 함수를 호출해 이 3장이 합인지 검사한다.

( Sset, Cset, Bset 3개 HashSet 생성하고 세 장의 카드 속성(S, C, B)을 각각 set에 추가한다.

하나라도 set 크기가 2면 합이 아니다.)

 

3. n번 반복하며 질의를 처리한다.

질의가 "H x y z"라면, 입력받은 세 인덱스를 정렬한 뒤 isH[x][y][z]가 1인지 확인한다.

값이 1이라면 올바른 합이므로 score를 1 증가시키고, 중복 방지를 위해 isH[x][y][z] 값을 증가시킨다.

값이 1이 아니라면 잘못된 합 선언으로 score를 1 감소시킨다.

 

4. 질의가 "G"라면, isH 배열에 아직 1인 값이 존재하는지 검사한다.

하나라도 남아 있다면 잘못된 결 선언으로 score를 1 감소시킨다.

모든 합이 이미 처리되어 1이 존재하지 않고, 이전에 결을 외친 적이 없다면 올바른 결 선언으로 간주하여 score를 3 증가시키고 isG를 true로 변경한다.

 

5. score를 출력한다.

 

종종 결합과 비슷한 Set이라는 보드게임을 하는데 이 문제를 보니 반가웠다.

재밌는 문제였다.