Plite
전자오락 공방
Plite
전체 방문자
오늘
어제
  • 분류 전체보기 (274)
    • 프로젝트 (18)
      • 완성 프로젝트 (3)
      • 프로젝트 진행 내역 (15)
    • 공부 및 정리 (241)
      • 백준 코드 (222)
      • C++ (8)
      • DirectX (2)
      • Unreal Engine (6)
      • 프로그래밍 패턴 (3)
    • 기타 (12)
      • 기타 주저리 (10)
    • 게임과 취미 (1)
    • 대문 (1)

블로그 메뉴

  • 홈
  • 프로젝트
  • 취미, 일상
  • 백준 프로필

공지사항

  • [Read Me]
  • 제 블로그에 방문하신 것을 환영합니다.

인기 글

태그

  • 정렬
  • SCC
  • 유니온 파인드
  • 브루트포스
  • 기하
  • 최소 스패닝 트리
  • 구현
  • 트라이
  • 조합론
  • KMP
  • 정수론
  • 이분탐색
  • 문자열
  • 백준
  • 위상 정렬
  • 세그먼트 트리
  • 우선순위큐
  • LCA
  • C++
  • 동적계획법
  • 투포인터
  • 트리
  • 분할정복
  • 수학
  • 누적합
  • 스택
  • UC++
  • 큐
  • 그래프
  • 백트래킹

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
Plite

전자오락 공방

[C++] 백준 - 25682번 문제
공부 및 정리/백준 코드

[C++] 백준 - 25682번 문제

2022. 11. 11. 12:58

25682번: 체스판 다시 칠하기 2 (acmicpc.net)

 

25682번: 체스판 다시 칠하기 2

첫째 줄에 정수 N, M, K가 주어진다. 둘째 줄부터 N개의 줄에는 보드의 각 행의 상태가 주어진다. B는 검은색이며, W는 흰색이다.

www.acmicpc.net

 

25682번 : 체스판 다시 칠하기 2


지민이는 자신의 저택에서 MN개의 단위 정사각형으로 나누어져 있는 M×N 크기의 보드를 찾았다. 어떤 정사각형은 검은색으로 칠해져 있고, 나머지는 흰색으로 칠해져 있다. 지민이는 이 보드를 잘라서 K×K 크기의 체스판으로 만들려고 한다.

체스판은 검은색과 흰색이 번갈아서 칠해져 있어야 한다. 구체적으로, 각 칸이 검은색과 흰색 중 하나로 색칠되어 있고, 변을 공유하는 두 개의 사각형은 다른 색으로 칠해져 있어야 한다. 따라서 이 정의를 따르면 체스판을 색칠하는 경우는 두 가지뿐이다. 하나는 맨 왼쪽 위 칸이 흰색인 경우, 하나는 검은색인 경우이다.

보드가 체스판처럼 칠해져 있다는 보장이 없어서, 지민이는 K×K 크기의 체스판으로 잘라낸 후에 몇 개의 정사각형을 다시 칠해야겠다고 생각했다. 당연히 K×K 크기는 아무데서나 골라도 된다. 지민이가 다시 칠해야 하는 정사각형의 최소 개수를 구하는 프로그램을 작성하시오.

 

입력


첫째 줄에 정수 N, M, K가 주어진다. 둘째 줄부터 N개의 줄에는 보드의 각 행의 상태가 주어진다. B는 검은색이며, W는 흰색이다.

 

 

출력


첫째 줄에 지민이가 잘라낸 K×K 보드를 체스판으로 만들기 위해 다시 칠해야 하는 정사각형 개수의 최솟값을 출력한다.

 

 


 

생각해 볼 점


1018번 문제를 누적합으로 풀어내는 문제입니다.

 

고려할 사항들은 다음과 같습니다.

 

1. 체스판은 두 종류 뿐입니다.

 

0, 0 지점이 W거나 B거나

 

 

 

2. (0, 0) 이 W인 체스판의 칠해야 할 갯수 = 체스판의 총 사각형 갯수 - B인 체스판의 갯수입니다.

 

즉, 한 쪽 체스판의 갯수만 구하면 나머지 갯수는 쉽게 구할 수 있습니다.

 

예시)

 

W 체스판 기준

 

WB  => 1개

BB

 

B 체스판 기준

 

WB  => 3개

BB

 

3. 누적합은 바꿔야할 사각형 갯수를 기준으로 더해나갑니다.

 

가로로 한번, 세로로 한번 더해줍니다.

 

예시) W 체스판 기준

 

 

 

4. 구하고자 하는 영역의 바꿀 사각형 갯수를 구하는 방법은

 

 

빨간 원은 더하고 파란 원은 뺍니다.

 

예시의 빨간 사각형 4개의 경우 

 

1 + 3 - 2 - 2 = 0으로

 

W 체스판 기준으로 바꿀 사각형이 하나도 없음을 알 수 있습니다.

(B 체스판 기준이면 4 - 0 = 4개 만큼 사각형을 바꿔 칠해야 합니다.)

 

왜 이렇게 더하고 빼야하는지는 누적합의 성질을 참고하세요.

 

코드


#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main()
{
    int N, M, K;
    scanf("%d %d %d", &N, &M, &K);

    //누적합 배열
    vector<vector<int>> arr(N + 1, vector<int>(M + 1, 0));

    //0, 0을 W 기준으로 작성 바꿔야할 타일 개수를 누적합 저장
    for(int y = 1; y <= N; y++)
    {
        char input[2001];
        scanf("%s", input);
        for(int x = 1; x <= M; x++)
        {
            //가로로 누적합
            if(input[x - 1] == 'B')
                arr[y][x] = arr[y][x - 1] + ((x + y) % 2 == 0);
            else
                arr[y][x] = arr[y][x - 1] + ((x + y) % 2 == 1);

            //세로로 누적합
            arr[y][x - 1] += arr[y - 1][x - 1];
        }
    }

    //누락된 마지막 열 세로로 누적합
    for(int y = 1; y <= N; y++)
        arr[y][M] += arr[y - 1][M]; 

    int const max_count = K * K;
    int ans = max_count;

    //누적합에서 바꿀 사각형 갯수 계산
    for(int y = K; y <= N; y++)
    {
        for(int x = K; x <= M; x++)
        {
            int summ = arr[y][x] + arr[y - K][x - K];
            summ -= arr[y][x - K] + arr[y - K][x];

            //WB 반전한 경우 고려
            ans = min(ans, min(summ, max_count - summ));
        }
    }
    printf("%d", ans);
    return 0;
}

 

그 외


 

저작자표시 (새창열림)

'공부 및 정리 > 백준 코드' 카테고리의 다른 글

[C++] 백준 - 1202번 문제  (0) 2022.11.18
[C++] 백준 - 9935번 문제  (0) 2022.11.17
[C++]백준 - 17299번 문제  (0) 2022.11.08
[C++]백준 - 2143번 문제  (0) 2022.11.01
[C++] 백준 - 1799번 문제  (0) 2022.10.27
    '공부 및 정리/백준 코드' 카테고리의 다른 글
    • [C++] 백준 - 1202번 문제
    • [C++] 백준 - 9935번 문제
    • [C++]백준 - 17299번 문제
    • [C++]백준 - 2143번 문제
    Plite
    Plite
    개발 일지, 게임 이야기 등을 적어두는 공간입니다.

    티스토리툴바