https://www.acmicpc.net/problem/1285
행렬
문제와 비슷하다고 생각해서 전부다 뒤집을려고 하되 필요한 부분만 뒤집으면 된다고 생각했다. 그 이유는 동전을 두번다 뒤집게 되면 모든 동전이 두번 뒤집히기 때문에 원래대로 돌아오기 때문이다.N = int(input())
coins = [[0] * N for _ in range(N)]
inputArr = [list(input()) for _ in range(N)]
# 초기 입력 값으로 coins 배열 초기화
for i in range(N):
for j in range(N):
if inputArr[i][j] == 'H':
coins[i][j] = 1
# 행 반전 함수
def reverse_row(arr, i):
for j in range(N):
arr[i][j] = 1 - arr[i][j]
# 열의 뒤집힌 비트 카운트
def count_column_flips(arr):
total_flips = 0
for j in range(N):
cnt = sum(arr[i][j] for i in range(N))
total_flips += min(cnt, N - cnt) # 최적의 열 반전 횟수 선택
return total_flips
answer = float('inf')
# 모든 행 반전 조합 시도
for mask in range(1 << N):
# 원본 배열의 복사본 생성
tmp = [row[:] for row in coins]
# 비트마스크를 이용해 각 행을 반전
for i in range(N):
if mask & (1 << i):
reverse_row(tmp, i)
# 최소 열 반전을 계산
flips = count_column_flips(tmp)
answer = min(answer, flips)
print(answer)
동전을 한 행이나 열을 뒤집어서 최소한의 동전만 뒷면을 보게 만드는 문제이다. 이 때, 어떻게 뒤집느냐에 따라 순서가 동전을 뒤집는데 영향을 줄 수 있다고 생각할 수 있으나 어떻게 뒤집든 같은 결과가 나오기 때문에 동전을 뒤집는 순서는 영향을 주지 않는다.
먼저 모든 행을 뒤집는 모든 경우의 수 즉, 모든 부분집합을 구하는 방식으로 접근한다. 비트를 사용해서 모든 부분집합을 기준으로 할 배열을 복사해두고 행을 그 케이스에 따라 뒤집는다. 그리고 그 경우에서의 최소로 뒷면이 나오는 갯수를 구한다.
뒷면이 최소가 되는 갯수는 각 열에 대해서 H
와 T
의 갯수 중 작은 것을 구하는 것이다. 결국 뒤집든 안 뒤집든 적은 쪽이 뒤집고 나서의 T
가 될 것이기 때문에 꼭 뒤집지 않더라고 우리는 각 열에서의 갯수를 구할 수 있다. 이를 다 더한 후 답을 갱신 시키면 된다.
이렇게 Python으로 백준의 "동전 뒤집기" 문제를 해결해보았습니다. 코드와 개념 설명을 참고하여 문제를 해결하는 데 도움이 되셨길 바랍니다! 😊