728x90
< 문제 >
< 풀이 >
코드 변수 정의
- function : check_pattern
- pattern1, pattern2 : 체스판의 시작이 W인 패턴, 체스판의 시작이 B인 패턴
- replace1 : pattern1인 체스판인 경우 다시 칠해야 하는 칸의 수
- replace2 : pattern2인 체스판인 경우 다시 칠해야 하는 칸의 수
- function : f
- compare_board : 주어진 보드에서 잘라낸 8X8 체스판
- min_ans : 체스판에서 다시 칠해야 하는 정사각형의 최소 개수
Brute Force
시간복잡도 : O(NXM)
def check_pattern(board):
pattern1 = ['WBWBWBWB', 'BWBWBWBW'] * 4 # 시작이 W인 패턴
pattern2 = ['BWBWBWBW', 'WBWBWBWB'] * 4 # 시작이 B인 패턴
# pattern1인 경우 다시 칠해야 하는 칸의 수
replace1 = sum(board[i][j] != pattern1[i][j] for i in range(8) for j in range(8))
# pattern2인 경우 다시 칠해야 하는 칸의 수
replace2 = sum(board[i][j] != pattern2[i][j] for i in range(8) for j in range(8))
# W, B로 시작하는 체스판 중 다시 칠하는 칸의 수가 더 적은 값을 반환한다.
return min(replace1, replace2)
def f():
N, M = map(int, input().split())
board = [input().strip() for _ in range(N)]
min_ans = float('inf') # 다시 칠해야 하는 정사각형의 최소 개수
# 주어진 보드로 만들 수 있는 8X8 체스판의 모든 경우의 수
for i in range(N - 7):
for j in range(M - 7):
compare_board = [board[x][j:j+8] for x in range(i, i+8)] # 8X8 체스판
min_ans = min(min_ans, check_pattern(compare_board))
return min_ans
print(f())
풀이 방식
- check_pattern 함수 : 8X8 체스판의 색칠 변경 횟수 계산
- 입력된 8X8 크기의 board를 두 가지 체스판 패턴과 비교하여 변경해야 하는 칸의 개수를 구한다.
- pattern1 : 체스판이 'W'로 시작하는 경우의 올바른 패턴
- WBWBWBWB
BWBWBWBW
WBWBWBWB
BWBWBWBW
WBWBWBWB
BWBWBWBW
WBWBWBWB
BWBWBWBW
- WBWBWBWB
- pattern2 : 체스판이 'B'로 시작하는 경우의 올바른 패턴
- BWBWBWBW
WBWBWBWB
BWBWBWBW
WBWBWBWB
BWBWBWBW
WBWBWBWB
BWBWBWBW
WBWBWBWB
- BWBWBWBW
- replace1 : 현재 보드와 pattern1을 비교하여 다른 문자의 개수를 계산
- replace2 : 현재 보드와 pattern2를 비교하여 다른 문자의 개수를 계산
- min(replace1, replace2) : 두 개의 패턴 중 더 적은 변경 횟수를 반환한다.
- f 함수 : 최소 수정 횟수 찾기
- 주어진 NXM 보드에서 8X8 크기의 모든 부분 보드를 확인하여 최소 수정 횟수를 구한다.
- board는 input값에 strip()을 사용하여 불필요한 공백을 제거한다.
- 체스판은 8X8 크기여야 하므로, 시작 위치 (i, j)는 (N-7, M-7) 범위 내에서 선택한다.
- 현재 (i, j) 위치에서 8X8 크기의 부분 보드를 추출한다.
- board[i][j:j+8]를 통해 8개의 연속된 행을 가져온다.
- check_pattern(compare_board)를 호출하여 현재 보드에서 최소 변경 횟수를 구하고 min_ans를 업데이트한다.
< 회고 >
브루트 포스(Brute Force)
브루트 포스는 가능한 모든 경우의 수를 직접 탐색하여 정답을 찾는 방법
특징
- 모든 경우의 수를 검사하기 때문에 정확한 정답을 보장한다.
- 구현이 간단하며, 직관적으로 이해하기 쉽다.
- 경우의 수가 많아지면 시간 복잡도가 증가하여 비효율적일 수 있다.
- 데이터의 크기가 작을 때 적절한 방법이다.
동작 방식
- 모든 가능한 조합을 생성한다.
- 각 경우를 검사하여 조건을 만족하는지 확인한다.
- 최적의 답을 선택한다.
예제
- 비밀번호 해킹 예제
- 비밀번호가 4 자리(0000 ~ 9999)라면, 브루트 포스 방식으로 0000부터 9999까지 전부 시도하여 맞는 비밀번호를 찾을 수 있다.
- 모든 조합을 시도하는 무식한 방법이지만 반드시 정답을 찾는다.
- 8 x 8 체스판 다시 칠하기 (위 문제)
- 모든 가능한 위치에서 탐색하여 최적의 정답을 찾는 방법이다.
- 체스판을 자를 수 있는 모든 경우(부분 보드)를 탐색한다.
- 각 경우에서 다시 칠해야 하는 최소 횟수를 계산한다.
- 최소 횟수를 갱신하면서 정답을 찾는다.
- 모든 가능한 위치에서 탐색하여 최적의 정답을 찾는 방법이다.
시간 복잡도
- 일반적으로 가능한 모든 경우를 탐색하기 때문에 시간 복잡도가 크다는 단점이 있다.
- n자리 비밀번호 찾기 : O(10^n)
- n개의 원소로 만들 수 있는 모든 순열 : O(n!)
- n x m 체스판에서 8 x 8 탐색 : O(NM)
개선 방법
- 백트래킹(Backtracking) → 불필요한 경우의 수를 조기에 가지치기하여 탐색 속도를 향상한다.
- 가지치기(Pruning) → 조건을 만족하지 않는 경우 더 깊이 탐색하지 않는다.
- 다이나믹 프로그래밍(DP) → 중복 계산을 줄여 효율적으로 해결한다.
- 비트마스킹(Bitmasking) → 브루트 포스를 빠르게 수행하는 기법이다.
브루트 포스를 사용하는 경우
- 가능한 경우의 수가 적을 때
- 확실한 정답을 찾고 싶을 때
- 문제를 더 효율적인 방법으로 해결하기 전 아이디어를 구상할 때
728x90
'coding_test > 항해99 코테스터디 TIL' 카테고리의 다른 글
99클럽 코테 스터디 _ 13일차 TIL (백트래킹) (0) | 2025.02.05 |
---|---|
99클럽 코테 스터디 _ 12일차 TIL (브루트 포스) (0) | 2025.02.04 |
99클럽 코테 스터디 _ 10일차 TIL (BFS) (0) | 2025.01.24 |
99클럽 코테 스터디 _ 9일차 TIL (이분 그래프, BFS) (0) | 2025.01.23 |
99클럽 코테 스터디 _ 8일차 TIL (BFS, DFS, Union-Find, Flood Fill) (0) | 2025.01.22 |