본문 바로가기
백준

[백준 16932] 모양 만들기, C++

by 황인태(intaehwang) 2020. 1. 31.
반응형

https://www.acmicpc.net/problem/16932

 

16932번: 모양 만들기

N×M인 배열에서 모양을 찾으려고 한다. 배열의 각 칸에는 0과 1 중의 하나가 들어있다. 두 칸이 서로 변을 공유할때, 두 칸을 인접하다고 한다. 1이 들어 있는 인접한 칸끼리 연결했을 때, 각각의 연결 요소를 모양이라고 부르자. 모양의 크기는 모양에 포함되어 있는 1의 개수이다. 배열의 칸 하나에 들어있는 수를 변경해서 만들 수 있는 모양의 최대 크기를 구해보자.

www.acmicpc.net

 본 문제는 0을 1로 바꿨을 때, 인접한 칸의 1의 개수가 최대인 크기를 구하는 문제다. 입력의 크기가 최대 1,000이므로 입력된 배열의 전체를 탐색하면서 0을 1로 바꾸고, 1의 개수를 확인하면 시간초과가 나온다. 따라서, 다른 방법으로 문제해결을 해야한다.

  1. bfs로 전체 탐색하여 인접한 1의 그룹을 나눈다.
  2. 전체 탐색을 하면서 0일 때, 인접한 칸이 1인지 확인
  3. 1일 경우 해당 그룹의 개수를 더한다.
    • 이때, 그룹의 중복이 있을 수 있으니, 중복된 그룹은 제거한다.
  4. 만들 수 있는 모든 경우를 확인하면서 최댓값을 찾는다.
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#include <cstdio>
#include <queue>
#include <vector>
#include <algorithm>
 
using namespace std;
 
int d[1001][1001];
int a[1001*1001];
int dx[] = {1-100};
int dy[] = {001-1};
int n, m;
bool chk[1001][1001];
bool c[1001];
 
int main() {
    scanf("%d %d"&n ,&m);
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            scanf("%d"&d[i][j]);
        }
    }
    queue<pair<intint>> q;
    int cal = 0;
    // bfs 탐색
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            if (!chk[i][j] && d[i][j] == 1) {
                cal += 1;
                q.push(make_pair(i, j));
                chk[i][j] = true;
                d[i][j] = cal;
                int cnt = 1;
                while (!q.empty()) {
                    int x = q.front().first;
                    int y = q.front().second;
                    q.pop();
                    for (int k = 0; k < 4; k++) {
                        int nx = x + dx[k];
                        int ny = y + dy[k];
                        if (nx >= 0 && nx < n && ny >= 0 && ny < m) {
                            if (!chk[nx][ny] && d[nx][ny] == 1) {
                                cnt += 1;
                                d[nx][ny] = cal;
                                chk[nx][ny] = true;
                                q.push(make_pair(nx, ny));
                            }
                        }
                    }
                }
                a[cal] = cnt;
            }
        }
    }
    vector<int> ans;
    for (int x = 0; x < n; x++) {
        for (int y = 0; y < m; y++) {
            if (d[x][y] == 0) {
                vector<int> add;
                for (int k = 0; k < 4; k++) {
                    int nx = x + dx[k];
                    int ny = y + dy[k];
                    if (nx >= 0 && nx < n && ny >= 0 && ny < m) {
                        // 인접하 칸이 1일 경우 (0이 아닐 경우)
                        if (d[nx][ny] != 0) {
                            add.push_back(d[nx][ny]);
                        }
                    }
                }
                // 중복값 제거
                sort(add.begin(), add.end());
                add.erase(unique(add.begin(), add.end()), add.end());
                int result = 0;
                // 최댓값 탐색
                for (int k = 0; k < add.size(); k++) {
                    result += a[add[k]];
                }
                ans.push_back(result);
            }
        }
    }
    sort(ans.rbegin(), ans.rend());
    printf("%d\n", ans[0]+1);
}
cs
반응형

'백준' 카테고리의 다른 글

[백준 17089] 세 친구, C++  (0) 2020.02.04
[백준 17088] 등차수열 변환, C++  (0) 2020.02.02
[백준 16236] 아기 상어, C++  (0) 2020.01.31
[백준 15686] 치킨 배달, C++  (0) 2020.01.31
[백준 1932] 정수 삼각형, C++  (0) 2020.01.15
Buy me a coffeeBuy me a coffee

댓글