반응형

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

 

17142번: 연구소 3

인체에 치명적인 바이러스를 연구하던 연구소에 승원이가 침입했고, 바이러스를 유출하려고 한다. 바이러스는 활성 상태와 비활성 상태가 있다. 가장 처음에 모든 바이러스는 비활성 상태이고

www.acmicpc.net

1. 백트래킹으로 활성화 할 바이러스 선택

  - 2차원 배열에서 백트래킹하면 시간초과

  - arr[i][j] = 2인 {i, j} 값을 벡터에 저장시킨 뒤, 해당 벡터에 대해서 백트래킹 수행

 

2. m개 활성시켰으면 BFS로 시간 계산

  - arr[i][j]에서 BFS 수행하면 입력이 변경되므로, 다음 백트래킹 수행 시 계산 잘못됨

  - arr[i][j]가 아니라 copy_arr[i][j]에서 BFS 수행

 

0: 빈 칸

1: 벽

2: 바이러스 (비활성화)

3: 바이러스 (활성화)

 

소스코드

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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#include <iostream>
#include <queue>
#include <algorithm>
#include <cstring>
#include <vector>
#define rep(i,n) for(int i=0;i<n;i++)
#define pii pair<intint>
using namespace std;
queue<pii> q;
vector<pii> virus;
int n, m, arr[51][51], copy_arr[51][51], zero_cnt, ans = 1e9;
bool visited[51][51];
int dx[] = { -1010 };
int dy[] = { 010-1 };
void input();
void bfsInit() {
    memset(visited, 0sizeof(visited));
    while (!q.empty())
        q.pop();
    zero_cnt = 0;
    rep(i, n) {
        rep(j, n) {
            copy_arr[i][j] = arr[i][j];
            // 활성화된 바이러스를 queue에 삽입하고 방문처리
            if (copy_arr[i][j] == 3) {
                q.push({ i,j });
                visited[i][j] = 1;
            }
            // 빈 칸의 개수 체크
            else if (copy_arr[i][j] == 0) zero_cnt++;
        }
    }
}
// return 시간(초)
int bfs() {
    int cnt = 0;
    bfsInit();
    while (!q.empty()) {
        int size = q.size();
        // 빈 칸 없으면 종료
        if (zero_cnt == 0break;
        while (size--) {
            pii now = q.front(); q.pop();
            int x = now.first;
            int y = now.second;
            visited[x][y] = 1;
            rep(i, 4) {
                int nx = x + dx[i];
                int ny = y + dy[i];
                if (nx < 0 || nx >= n || ny < 0 || ny >= n || visited[nx][ny]) continue;
                // 1: 벽이라서 멈춤
                if (copy_arr[nx][ny] == 1continue;
 
                // 0, 2: 활성화 상태(3)로 변경 후 전파시킴
                else if (copy_arr[nx][ny] == 0 || copy_arr[nx][ny]==2) {
                    if (copy_arr[nx][ny] == 0) zero_cnt--;
                    copy_arr[nx][ny] = 3;
                    visited[nx][ny] = 1;
                    q.push({ nx, ny });
                }
                
                // 3: 이미 visited라서 걸러질 것
            }
        }
        cnt++;
    }
    return cnt;
}
 
void backTrackking(int idx, int cnt) {
    // 바이러스를 m개 만큼 활성화 시켰으면 bfs 실행
    if (cnt == m) {
        int ret = bfs();
 
        // 빈 칸 개수가 0개일 때만 갱신
        if (zero_cnt == 0)
            ans = min(ans, ret);
        return;
    }
 
    // 백트래킹으로 활성화시킬 바이러스 찾기
    for (int i = idx; i < virus.size(); i++) {
        int x = virus[i].first;
        int y = virus[i].second;
        if (arr[x][y] == 2) {
            arr[x][y] = 3;
            backTrackking(i, cnt + 1);
            arr[x][y] = 2;
        }
    }
}
// 1. 활성화 시킬 바이러스 선택하기 (백트래킹)
// 2. 시간 얼마나 걸리는지 계산하기 (bfs)
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    input();
    backTrackking(00);
    cout << (ans==1e9?-1:ans);
}
 
void input() {
    cin >> n >> m;
    rep(i, n) {
        rep(j, n) {
            cin >> arr[i][j];
            if (arr[i][j] == 2)
                virus.push_back({ i,j });
        }
    }
}
cs

 

반응형

'백준 > 삼성기출' 카테고리의 다른 글

백준 17837 [4%에서 틀렸습니다.]  (0) 2021.08.08
백준 17779 [복습 필수]  (0) 2021.08.06
백준 17143  (0) 2021.07.19
백준 5373 [복습필수]  (0) 2021.04.30
백준 16234  (0) 2021.04.30

+ Recent posts