본문 바로가기
Algorithm/BackJoon

1018번: 체스판 다시 칠하기

by 꼬부기가우는소리 2023. 6. 14.
728x90

 

- 관련 사이트: https://www.acmicpc.net/problem/1018

 

1018번: 체스판 다시 칠하기

첫째 줄에 N과 M이 주어진다. N과 M은 8보다 크거나 같고, 50보다 작거나 같은 자연수이다. 둘째 줄부터 N개의 줄에는 보드의 각 행의 상태가 주어진다. B는 검은색이며, W는 흰색이다.

www.acmicpc.net

 

하나씩 모두 비교하여 가장 최솟값을 구하였다.

 

1) (0, 0) 위치부터 시작 지점을 정하고 8 x 8 씩 잘라서 비교

    (예: 8 x 10인 경우, 시작 지점은 각각 (0, 0), (0, 1), (0, 2)가 된다.)

2) 시작 지점이 'B' 인 경우와 'W' 인 경우 각각 계산

3) 좌표 x, y가 짝수/홀수인지 확인하여 1)과 2) 에 대해 교체 필요한 개수 카운팅

4) 결과들을 비교하여 가장 작은 값 확인

5) 모든 계산 완료 후 가장 작은 값 출력

 

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

vector<string> matrix;

int check(int x, int y, char first, char second)
{
    int cnt = 0;
    for (int row = x; row < x + 8; row++)
    {
        for (int col = y; col < y + 8; col++)
        {
            bool row_even = (row % 2 == 0);
            bool col_even = (col % 2 == 0);
            if ((row_even && col_even || !row_even && !col_even) && matrix[row][col] != first)
                cnt++;
            else if ((row_even && !col_even || !row_even && col_even) && matrix[row][col] != second)
                cnt++;
        }
    }
    return cnt;
}

int main()
{
    int M, N;
    string str;

    cin >> M >> N;
    for (int i = 0; i < M; i++)
    {
        cin >> str;
        matrix.push_back(str);
    }
    
    int cnt;
    int result = 64;
    for (int x = 0; x <= M - 8; x++)
    {
        for (int y = 0; y <= N - 8; y++)
        {
            cnt = check(x, y, 'B', 'W');
            if (cnt < result) result = cnt;

            cnt = check(x, y, 'W', 'B');
            if (cnt < result) result = cnt;
        }
    }

    cout << result;
    return 0;
}

- 메모리: 2024 KB

- 시간: 0 ms

- 코드 길이: 1135 B

 

위의 코드에서 아래와 같이 몇가지 불필요한 로직을 제거해줄 수 있다.

 

1) (0, 0) 위치부터 시작 지점을 정하고 8 x 8 씩 잘라서 비교

    (예: 8 x 10인 경우, 시작 지점은 각각 (0, 0), (0, 1), (0, 2)가 된다.)

2) 시작 지점이 'B' 인 경우와 'W' 인 경우 각각 계산

3) 좌표 x, y의 합이 짝수/홀수인지 여부를 계산하여 1)과 2) 에 대해 교체 필요한 개수 카운팅

4) 이전 결과값, 'B'로 시작한 경우, 'W'로 시작된 경우(64 - 'B'로 시작한 경우) 중 가장 작은 값 확인 → min 함수 사용

5) 모든 계산 완료 후 가장 작은 값 출력

 

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

vector<string> matrix;

int check(int x, int y)
{
    int cnt = 0;
    for (int row = x; row < x + 8; row++)
    {
        for (int col = y; col < y + 8; col++)
        {
            if ((row + col) % 2 == 0 && matrix[row][col] != 'B'
             || (row + col) % 2 != 0 && matrix[row][col] != 'W')
             cnt++;
        }
    }
    return cnt;
}

int main()
{
    int M, N;
    string str;

    cin >> M >> N;
    for (int i = 0; i < M; i++)
    {
        cin >> str;
        matrix.push_back(str);
    }
    
    int cnt;
    int result = 64;
    for (int x = 0; x <= M - 8; x++)
    {
        for (int y = 0; y <= N - 8; y++)
        {
            cnt = check(x, y);
            result = min({cnt, 64 - cnt, result});
        }
    }

    cout << result;
    return 0;
}

- 메모리: 2024 KB

- 시간: 0 ms

- 코드 길이: 861 B

 

추가적으로, 교체 필요한 타일 여부를 확인 시 위의 코드의 경우 아래의 로직으로 확인해주고 있다.

1) x, y 좌표의 합이 짝수이면서 타일이 'W'인 경우

2) x, y 좌표의 합이 홀수이면서 타일이 'B'인 경우

 

1)이 'B'이고 2)가 'W'로 변경하여 계산하여도 상관 없다. 'B'든 'W'든 하나의 패턴을 확인한 후 "64 - 확인된 패턴 수"를 통해 다른 하나를 구해주고 있기 때문이다.

 

위의 로직을 비트 연산자를 통해 간단히 변경이 가능하다.

1) x, y 좌표의 합이 홀수인지 확인: (row + col) % 2 != 0 → (row + col) & 1

2) 타일이 'B'가 아닌지 확인: matrix[row][col] != 'B'

3) 1과 2를 통해 조건 확인

(row + col) % 2 == 0 && matrix[row][col] != 'B' || (row + col) % 2 != 0 && matrix[row][col] != 'W'

(row + col) & 1 ^ matrix[row][col] != 'B'

 

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

vector<string> matrix;

int check(int x, int y)
{
    int cnt = 0;
    for (int row = x; row < x + 8; row++)
    {
        for (int col = y; col < y + 8; col++)
        {
            cnt += ((row + col) & 1 ^ matrix[row][col] != 'B');
        }
    }
    return cnt;
}

int main()
{
    int M, N;
    string str;

    cin >> M >> N;
    for (int i = 0; i < M; i++)
    {
        cin >> str;
        matrix.push_back(str);
    }
    
    int cnt;
    int result = 64;
    for (int x = 0; x <= M - 8; x++)
    {
        for (int y = 0; y <= N - 8; y++)
        {
            cnt = check(x, y);
            result = min({cnt, 64 - cnt, result});
        }
    }

    cout << result;
    return 0;
}

- 메모리: 2024 KB

- 시간: 0 ms

- 코드 길이: 776 B

728x90

'Algorithm > BackJoon' 카테고리의 다른 글

1735번: 분수 합  (0) 2023.06.20
1436번: 영화감독 숌  (0) 2023.06.15
15964번: 이상한 기호  (0) 2023.06.14
10814번: 나이순 정렬  (0) 2023.06.13
1934번: 최소공배수  (0) 2023.06.12

댓글