[백준 25682번 C/C++] 체스판 다시 칠하기 2
[백준 25682번 C/C++] 체스판 다시 칠하기 2
https://www.acmicpc.net/problem/25682
25682번: 체스판 다시 칠하기 2
첫째 줄에 정수 N, M, K가 주어진다. 둘째 줄부터 N개의 줄에는 보드의 각 행의 상태가 주어진다. B는 검은색이며, W는 흰색이다.
www.acmicpc.net
해결전략
누적합, 동적 프로그래밍 Dynamic Programming DP
체스판 위에 k x k 크기의 정사각형을 놓았을 때, 정사각형 내의 체스판 칸 색깔을 바꿔서 모두 같은 색으로 만드는 데 필요한 최소 변경 횟수를 찾는다.
처음 시도한 코드 - 98%에서 실패
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
int n, m, k;
vector<vector<char>> v;
vector<vector<int>> change, dp;
int main(){
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cin >> n >> m >> k;
v.resize(n, vector<char>(m));
change.resize(n, vector<int>(m));
dp.resize(n, vector<int>(m));
for(int y = 0; y < n; y++){
for(int x = 0; x < m; x++){
cin >> v[y][x];
}
}
int paint = 2147483647;
if (v[0][0] == 'B')
{
for (int y = 0; y < n; y++) {
for (int x = 0; x < m; x++)
{
if ((y + x) % 2 == 0) {
if (v[y][x] == 'B') change[y][x] = 1;
}
else {
if (v[y][x] == 'W') change[y][x] = 1;
}
}
}
dp[0][0] = change[0][0];
for (int y = 0; y < n; y++) {
for (int x = 0; x < m; x++)
{
if (y == 0 && x == 0) continue;
if (y >= 1 && x == 0) dp[y][0] = dp[y - 1][0] + change[y][x];
else if (y == 0 && x >= 1) dp[0][x] = dp[0][x - 1] + change[y][x];
else
dp[y][x] = dp[y - 1][x] + dp[y][x - 1] - dp[y - 1][x - 1] + change[y][x];
if (y >= k - 1 && x >= k - 1)
{
int cnt;
if (y == k - 1 && x == k - 1) {
cnt = dp[y][x];
}
else if (y == k - 1 && x > k - 1){
cnt = dp[y][x] - dp[y][x - k];
}
else if (y > k - 1 && x == k - 1) {
cnt = dp[y][x] - dp[y - k][x];
}
else{
cnt = dp[y][x] - dp[y - k][x] - dp[y][x - k] + dp[y - k][x - k];
}
int total = k * k;
paint = min(paint, min(cnt, total - cnt));
}
}
}
}
else
{
for (int y = 0; y < n; y++) {
for (int x = 0; x < m; x++)
{
if ((y + x) % 2 == 0) {
if (v[y][x] == 'W') change[y][x] = 1;
}
else {
if (v[y][x] == 'B') change[y][x] = 1;
}
}
}
dp[0][0] = change[0][0];
for (int y = 0; y < n; y++) {
for (int x = 0; x < m; x++)
{
if (y == 0 && x == 0) continue;
if (y >= 1 && x == 0) dp[y][0] = dp[y - 1][0] + change[y][x];
else if (y == 0 && x >= 1) dp[0][x] = dp[0][x - 1] + change[y][x];
else
dp[y][x] = dp[y - 1][x] + dp[y][x - 1] - dp[y - 1][x - 1] + change[y][x];
if (y >= k - 1 && x >= k - 1)
{
int cnt;
if (y == k - 1 && x == k - 1) {
cnt = dp[y][x];
}
else if (y == k - 1 && x > k - 1) {
cnt = dp[y][x] - dp[y][x - k];
}
else if (y > k - 1 && x == k - 1) {
cnt = dp[y][x] - dp[y - k][x];
}
else {
cnt = dp[y][x] - dp[y - k][x] - dp[y][x - k] + dp[y - k][x - k];
}
int total = k * k;
paint = min(paint, min(cnt, total - cnt));
}
}
}
}
cout << paint << "\n";
return 0;
}
정답 코드
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
int n, m, k; // n과 m은 체스판의 크기, k는 바꿔야 하는 정사각형의 크기
vector<vector<int>> black, white; // black과 white는 각각 검은색과 흰색 칸의 개수를 나타내는 2차원 벡터
int main(){
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cin >> n >> m >> k;
black.resize(n+1, vector<int>(m+1));
white.resize(n+1, vector<int>(m+1));
char input;
for(int y = 1; y <= n; y++){
for(int x = 1; x <= m; x++){
cin >> input;
// 누적 합을 계산. (y, x) 위치까지의 검은색과 흰색 칸의 개수를 구한다.
black[y][x] = black[y - 1][x] + black[y][x - 1] - black[y - 1][x - 1];
white[y][x] = white[y - 1][x] + white[y][x - 1] - white[y - 1][x - 1];
// (y, x) 위치의 칸 색깔이 검은색인지 흰색인지를 확인하고, 해당 칸의 개수를 증가시킨다.
if ((y + x) % 2 == 0) {
if (input == 'B') white[y][x]++;
else black[y][x]++;
}
else {
if (input == 'W') white[y][x]++;
else black[y][x]++;
}
}
}
int cnt = k * k; // 최소 변경 횟수를 저장하는 변수. 초기값은 k*k로 설정
for (int y = k; y <= n; y++) {
for (int x = k; x <= m; x++)
{
// (y, x)를 우측 하단 꼭짓점으로 하는 kxk 크기의 정사각형 내의 검은색과 흰색 칸의 개수를 구한다.
int blackCnt = black[y][x] - black[y - k][x] - black[y][x - k] + black[y - k][x - k];
int whiteCnt = white[y][x] - white[y - k][x] - white[y][x - k] + white[y - k][x - k];
cnt = min(cnt, min(blackCnt, whiteCnt)); // 최소 변경 횟수를 갱신. 검은색과 흰색 칸의 개수 중 작은 것을 선택.
}
}
cout << cnt << "\n"; // 최소 변경 횟수를 출력
return 0;
}
'⭐ 코딩테스트 > 백준' 카테고리의 다른 글
[백준 7662번 C/C++] 이중 우선순위 큐 (1) | 2023.12.12 |
---|---|
[백준 7569번 C/C++] 토마토 (1) | 2023.12.11 |
[백준 1753번 C/C++] 최단경로 (0) | 2023.12.07 |
[백준 16928번 C/C++] 뱀과 사다리 게임 (0) | 2023.12.06 |
[백준 18808번 C/C++] 스티커 붙이기 (1) | 2023.12.05 |
댓글
이 글 공유하기
다른 글
-
[백준 7662번 C/C++] 이중 우선순위 큐
[백준 7662번 C/C++] 이중 우선순위 큐
2023.12.12 -
[백준 7569번 C/C++] 토마토
[백준 7569번 C/C++] 토마토
2023.12.11 -
[백준 1753번 C/C++] 최단경로
[백준 1753번 C/C++] 최단경로
2023.12.07 -
[백준 16928번 C/C++] 뱀과 사다리 게임
[백준 16928번 C/C++] 뱀과 사다리 게임
2023.12.06