알고리즘(백준 등) 공부/백준(자바)

백준 1285번: 동전 뒤집기

posite 2026. 2. 27. 13:11

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

 

앞 뒤로 이루어진 동전이 NxN 행렬 형태로 주어질 때, 행 혹은 열 단위로 뒤집어서 뒷면의 최소 갯수를 출력하는 문제이다.

처음에는 단순히 다 뒤집으면 되지 않을까? 생각했지만, 20x20 만 되어도 2^(20 * 20)의 경우의 수가 발생되어 시간 초과가 발생하여 반려하였다. 그러한 경우의 수 중 어떠한 행을 뒤집을지 정하면 열들을 뒤집는 최선의 경우의 수는 정해진다는 것을 알게 되었다. 원하는 행이 뒤집어 진 후, 특정 열을 뒤집는 경우는 뒷면의 갯수가 최소가 되는 경우일 때만 뒤집으면 되기 때문이다.

 

이러한 과정을 최적화하기 위해 각 열을 하나의 정수로 저장한다. cols[j]의 i번째 비트는 i행 j열의 동전 상태를 의미한다.

int[] cols = new int[N];
for (int i = 0; i < N; i++) {
    String line = br.readLine();
    for (int j = 0; j < N; j++) {
        if (line.charAt(j) == 'T') {
            cols[j] |= (1 << i);
        }
    }
}

 

 

행 뒤집기는 cols[j]와 뒤집을 행들의 집합 mask를 XOR 연산하여 행 뒤집기를 한 번에 계산한다. 이를 빠르게 하기 위해 Integer.bitCount()를 사용한다.

int answer = Integer.MAX_VALUE;

for (int mask = 0; mask < (1 << N); mask++) {
    int currentTotalTails = 0;
    
    for (int j = 0; j < N; j++) {
        int tailCount = Integer.bitCount(cols[j] ^ mask);
        currentTotalTails += Math.min(tailCount, N - tailCount);
    }
    
    if (currentTotalTails < answer) {
        answer = currentTotalTails;
    }
}

 

 

최종 코드는 다음과 같다.

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

public class 동전뒤집기1285 {
    
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int N = Integer.parseInt(br.readLine());
        int[] cols = new int[N];
        for (int i = 0; i < N; i++) {
            String line = br.readLine();
            for (int j = 0; j < N; j++) {
                if (line.charAt(j) == 'T') {
                    cols[j] |= (1 << i);
                }
            }
        }
        
        int answer = Integer.MAX_VALUE;
        
        for (int mask = 0; mask < (1 << N); mask++) {
            int currentTotalTails = 0;
            
            for (int j = 0; j < N; j++) {
                int tailCount = Integer.bitCount(cols[j] ^ mask);
                currentTotalTails += Math.min(tailCount, N - tailCount);
            }
            
            if (currentTotalTails < answer) {
                answer = currentTotalTails;
            }
        }
        
        System.out.print(answer);
    }
}