카테고리 없음

백준 10026 (C++) 적록색약

akinakamori 2021. 12. 15. 19:23
728x90
SMALL

유형

2차원 배열의 인접한 부분을 bool형 배열로 체크해가며 탐색하는 문제이다.

비슷한 문제를 풀어본 적이 없다면,

해결의 실마리조차 모르겠다면 아래 글을 참고하자.

 

2021.09.26 - [PS/백준] - 백준 4963번 (C++) 섬의 개수

 

백준 4963번 (C++) 섬의 개수

구글링 해서 풀었다면? 그래프 이론을 공부한 뒤에도 이 문제의 해답이 떠오르지 않는다면, 이 문제의 풀이를 암기하고, 비슷한 응용 문제를 풀어보는 게 효율적인 학습법일 것 같다. https://www.ac

synodic.tistory.com

 

구현 아이디어

bfs로 탐색하면서, 탐색한 곳은 bool 배열로 체크해주면 

섬처럼 묶인 부분들의 개수를 셀 수 있다.

적록색약인 경우와 아닌 경우 각각의 탐색 조건이 다를 것이다.

 

이를테면 색약인 경우 초록색과 빨간색을 구분하여 탐색하면 안된다.

그러므로 색약의 경우 호출하는 함수(bfs2)에서는

1. 현재의 색 (arr[x][y])와 탐색할 색(arr[nx][ny])가 같으면
2. 현재의 색이 red, 다음 탐색할 색이 green이면
3. 다음의 색이 red, 현재의 색이 green이면

세 가지 조건 중 하나라면 이어졌다(인접해있다, 연결되어있다)고 볼 수 있다.

 

 

나는 너비 우선 탐색을 사용했으나, 깊이 우선 탐색을 사용하여도 해결할 수 있는 문제이다.

깊이 우선 탐색으로 구현하다가 막혀서 이 글을 보게되었다면, 먼저 자신이 선택한 방법으로 끝까지 구현해보길 감히 추천한다...

 

 

DFS로 구현하기

 

2021.11.27 - [PS/백준] - 백준 2583 (C++) 영역 구하기

 

백준 2583 (C++) 영역 구하기

아이디어 1. input 2차원 배열을 예제의 모양대로 처럼 표현하기 위해서 그대로 넣을 수 없고 for (int i = y1; i < y2; i++) { for (int j = x1; j < x2; j++) { arr[m-i-1][j] = 1; } } 를 거쳐야 한다. 2. dfs..

synodic.tistory.com

 

위 글을 참조하면 dfs로 비슷한 문제를 해결하는 코드를 볼 수 있다.

 

 

코드

#include <iostream>
#include <algorithm>
#include <string>
#include <queue>
using namespace std;
using ll = long long;

int n, m, cnt1 = 0, cnt2 = 0;
int dx[] = {1, 0, -1, 0};
int dy[] = {0, -1, 0, 1};
char arr[102][102];
bool visited[102][102];
string s;

void bfs(int i, int j) {
    queue<pair<int, int> > q;
    q.push({i, j});
    
    while (!q.empty()) {
        int x = q.front().first;
        int y = q.front().second;
        // visited[x][y] = true;
        q.pop();
        
        for (int i = 0; i < 4; i++) {
            int nx = x + dx[i];
            int ny = y + dy[i];
            if (nx < 0 || nx >= n || ny < 0 | ny >= m) {
                continue;
            }
            if (!visited[nx][ny] && arr[x][y] == arr[nx][ny]) {
                visited[nx][ny] = true;
                q.push({nx, ny});
            }
        }
    }
    return;
}

void bfs2(int i, int j) { // 적록색맹의 경우
    queue<pair<int, int> > q;
    q.push({i, j});
    
    while (!q.empty()) {
        int x = q.front().first;
        int y = q.front().second;
        //visited[x][y] = true;
        q.pop();
        
        for (int i = 0; i < 4; i++) {
            int nx = x + dx[i];
            int ny = y + dy[i];
            if (nx < 0 || nx >= n || ny < 0 | ny >= m || visited[nx][ny]) {
                continue;
            }
            if (arr[x][y] == arr[nx][ny]) {
                visited[nx][ny] = true;
                q.push({nx, ny});
            }
            else if (arr[x][y] == 'R' && arr[nx][ny] == 'G') {
                visited[nx][ny] = true;
                q.push({nx, ny});
            }
            else if (arr[x][y] == 'G' && arr[nx][ny] == 'R') {
                visited[nx][ny] = true;
                q.push({nx, ny});
            }
        }
    }
    return;
}
int main(void) {
    ios_base::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cin >> n;
    for (int i = 0; i < n; i++) {
        cin >> s;
        for (int j = 0; j < s.size(); j++) {
            arr[i][j] = s[j];
            visited[i][j] = false;
        }
    }
    m = s.size();
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            if (!visited[i][j]) {
                bfs(i, j);
                cnt1++;
            }
        }
    }
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            visited[i][j] = false;
        }
    }
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            if (!visited[i][j]) {
                bfs2(i, j);
                cnt2++;
            }
        }
    }
    cout << cnt1 << " " << cnt2;
    return 0;
}

 

 

 

728x90
LIST