반응형
1018번: 체스판 다시 칠하기
첫째 줄에 N과 M이 주어진다. N과 M은 8보다 크거나 같고, 50보다 작거나 같은 자연수이다. 둘째 줄부터 N개의 줄에는 보드의 각 행의 상태가 주어진다. B는 검은색이며, W는 흰색이다.
www.acmicpc.net
<풀이과정>
처음에는 문제를 이해하고 풀이접근부터 어려웠던 문제다... 항상 이차원 배열로 생각하는 게 아직 어려운 것 같다...
우선 정답 8x8 보드와 입력값으로 주어진 n x m보드의 흑백 위치를 비교하면서 다르면 카운트해줘서 값의 최솟값을 출력하면, 우리가 원하는 가장 적게 다시 칠해야 되는 경우의 수를 얻을 수 있다고 이해했다.
그렇다면 먼저 입력값을 배열로 받아주고, 초기 배열의 보드를 8x8의 크기만큼 잘라서 비교하는 것을 반복해서 그중 가장 작은 값을 선택하면 된다. 풀이 구상은 어느정도 가능했다. 하지만 아직, 코드로 구현하는 부분이 미숙했다. 찾아보면서 코드의 작동방식을 확인하고, 이해했다. 내 것으로 만들기 위해 자주 들여다봐야겠다! 그리고, 간결한 코드 작성을 위해 리스트 컴프리헨션 기법을 공부했다.
동적계획법으로도 도전하였지만, 결국 못했다... 좀더 공부한 후 도전해 봐야겠다.
N, M = map(int, input().split())
board = [input() for _ in range(N)] # 보드 입력 받기
def count_min(board):
chess1 = ['BWBWBWBW', 'WBWBWBWB'] * 4 #흑으로 시작하는 경우
chess2 = ['WBWBWBWB', 'BWBWBWBW'] * 4 #백으로 시작하는 경우
cnt1, cnt2 = 0, 0 #차이값 저장 변수 0 으로 초기화
for i in range(8):
for j in range(8):
if board[i][j] != chess1[i][j]: #비교하면서 다르면 차이값 1씩 올리기
cnt1 += 1
if board[i][j] != chess2[i][j]:
cnt2 += 1
return min(cnt1, cnt2) #둘중 차이값 적은 보드 선택
answer = N * M # 초기값 설정
for i in range(N - 7):
for j in range(M - 7):
chess_board = [board[i+k][j:j+8] for k in range(8)] #리스트 컴프리헨션으로 작성 연습! k는 0~7까지 반복해서 받음
# 8x8 체스판 슬라이싱을 통해 만들기!
# i부터 i+7까지의 행을 슬라이싱한 뒤,각 행에서 j부터 j+7까지의 연속된 열을 슬라이싱한 리스트를 생성한다.
# k 변수로 0부터 7까지 반복한다 따라서, board의 i부터 i+7까지의 행을 만들고, 각 행에서 j부터 j+7까지의 연속된 열을 8x8 크기의 체스판 조각을 chess_board 변수에 할당한다.
temp = count_min(chess_board) # 현재 체스판에서의 최솟값 계산
answer = min(answer, temp) # 현재 값과 최솟값 비교하여 갱신
print(answer) # 결과 출력