일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 |
- 양과 늑대
- bottomscaffold
- NavGraph
- mutableStateOf
- derivedstateof
- compose
- 선언형 ui
- NavHost
- JCF
- 2989번
- 명령형ui
- Java
- remembercoroutinescope
- State
- 자바
- clean coder
- 명령형 ui
- mutablestate
- 선언형ui
- 클린아키텍처
- BottomSheet
- rememberupdatedstate
- apollo3
- snapshotflow
- producestate
- 2022 KAKAO BLIND RECRUITMENT
- genarics
- 안드로이드
- ModalBottomSheet
- 2022 kakao blind
- Today
- Total
버미
백준 25682번 - 체스판 다시 칠하기 2(C++) 본문
체스판 다시 칠하기 2
1 초 | 256 MB | 4290 | 1717 | 1282 | 39.592% |
문제
지민이는 자신의 저택에서 MN개의 단위 정사각형으로 나누어져 있는 M×N 크기의 보드를 찾았다. 어떤 정사각형은 검은색으로 칠해져 있고, 나머지는 흰색으로 칠해져 있다. 지민이는 이 보드를 잘라서 K×K 크기의 체스판으로 만들려고 한다.
체스판은 검은색과 흰색이 번갈아서 칠해져 있어야 한다. 구체적으로, 각 칸이 검은색과 흰색 중 하나로 색칠되어 있고, 변을 공유하는 두 개의 사각형은 다른 색으로 칠해져 있어야 한다. 따라서 이 정의를 따르면 체스판을 색칠하는 경우는 두 가지뿐이다. 하나는 맨 왼쪽 위 칸이 흰색인 경우, 하나는 검은색인 경우이다.
보드가 체스판처럼 칠해져 있다는 보장이 없어서, 지민이는 K×K 크기의 체스판으로 잘라낸 후에 몇 개의 정사각형을 다시 칠해야겠다고 생각했다. 당연히 K×K 크기는 아무데서나 골라도 된다. 지민이가 다시 칠해야 하는 정사각형의 최소 개수를 구하는 프로그램을 작성하시오.
입력
첫째 줄에 정수 N, M, K가 주어진다. 둘째 줄부터 N개의 줄에는 보드의 각 행의 상태가 주어진다. B는 검은색이며, W는 흰색이다.
출력
첫째 줄에 지민이가 잘라낸 K×K 보드를 체스판으로 만들기 위해 다시 칠해야 하는 정사각형 개수의 최솟값을 출력한다.
제한
- 1 ≤ N, M ≤ 2000
- 1 ≤ K ≤ min(N, M)
예제 입력 1
4 4 3
BBBB
BBBB
BBBW
BBWB
예제 출력 1
2
예제 입력 2
8 8 8
WBWBWBWB
BWBWBWBW
WBWBWBWB
BWBBBWBW
WBWBWBWB
BWBWBWBW
WBWBWBWB
BWBWBWBW
예제 출력 2
1
예제 입력 3
10 13 10
BBBBBBBBWBWBW
BBBBBBBBBWBWB
BBBBBBBBWBWBW
BBBBBBBBBWBWB
BBBBBBBBWBWBW
BBBBBBBBBWBWB
BBBBBBBBWBWBW
BBBBBBBBBWBWB
WWWWWWWWWWBWB
WWWWWWWWWWBWB
예제 출력 3
30
예제 입력 4
9 23 9
BBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBWWWWWWWW
예제 출력 4
40
문제 풀이
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int n, m, k;
vector<vector<int>> prefix_sum;
vector<vector<char>> board;
int chess(char color) {
prefix_sum.assign(n + 1, vector<int>(m + 1, 0));
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
int value = ((i + j) % 2 == 0) ? (board[i][j] == color) : (board[i][j] != color);
prefix_sum[i + 1][j + 1] = prefix_sum[i][j + 1] + prefix_sum[i + 1][j] - prefix_sum[i][j] + value;
}
}
int count = 99999999;
for (int i = 0; i <= n - k; i++) {
for (int j = 0; j <= m - k; j++) {
count = min(count, prefix_sum[i + k][j + k] - prefix_sum[i + k][j] - prefix_sum[i][j + k] + prefix_sum[i][j]);
}
}
return count;
}
int main() {
cin >> n >> m >> k;
board.assign(n, vector<char>(m));
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
cin >> board[i][j];
}
}
cout << min(chess('B'), chess('W')) << endl;
return 0;
}
아이디어
누적 합을 이용했으며 (M x N) 크기의 체스판을 (K x K) 크기의 정사각 체스판으로 다시 만들어야 한다.
1행 1열을 W으로 시작할지 B으로 시작할지에 따라 최솟값이 달라질 수 있기 때문에 먼저 B일 때와 W일 때, 2가지로 나눈다.
규칙에 맞게 1행 1열(i = 1, j = 1) 경우 부터 (i + j)%2의 조건으로 규칙에 맞는 색으로 칠해야하는지 아닌지 결정한다.
칠해야하는 경우라면 +1 을 해주어서 prefix_sum에 누적해주며 2중 반복문을 끝으로 누적 합이 계산된다.
이제 (K x K) 크기의 체스판을 최소로 칠할 수 있는 경우를 찾아야 하는데 이는 2번째 2중 반복문으로 일일이 순회하며 최솟값을 찾는다.
'코딩 트레이닝' 카테고리의 다른 글
프로그래머스 - 신고 결과 받기(C++) (0) | 2023.08.13 |
---|---|
프로그래머스 - 달리기 경주(C++) (0) | 2023.08.12 |
프로그래머스 - 성격 유형 검사하기(C++) (0) | 2023.08.10 |
백준 11660번 - 구간 합 구하기 5(C++) (0) | 2023.08.09 |
백준 11054번 - 가장 긴 바이토닉 부분 수열(C++) (0) | 2023.08.08 |