-

[삼성SW테스트] 백준 14502번 - 연구소 (정답률 54%) 본문

1-1. 삼성 SW 테스트

[삼성SW테스트] 백준 14502번 - 연구소 (정답률 54%)

asdklfjlasdlfkj 2020. 1. 13. 10:25

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

 

14502번: 연구소

인체에 치명적인 바이러스를 연구하던 연구소에서 바이러스가 유출되었다. 다행히 바이러스는 아직 퍼지지 않았고, 바이러스의 확산을 막기 위해서 연구소에 벽을 세우려고 한다. 연구소는 크기가 N×M인 직사각형으로 나타낼 수 있으며, 직사각형은 1×1 크기의 정사각형으로 나누어져 있다. 연구소는 빈 칸, 벽으로 이루어져 있으며, 벽은 칸 하나를 가득 차지한다.  일부 칸은 바이러스가 존재하며, 이 바이러스는 상하좌우로 인접한 빈 칸으로 모두 퍼져나갈 수 있다.

www.acmicpc.net

삼성 SW 테스트 기출문제다.

풀 수 있는 방법은

1. 백트래킹으로 놓을 수 있는 공간에 벽 세 개 설치하고 결과 구하기

2. 순열 (next_permutation함수와 플래그)로 풀기

정도가 있다.

 

두 방법 모두 활용해 풀어보았으며, 코드는 아래와 같다.

1. 백트래킹 (68ms)

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
#include <iostream>
#include <queue>
#include <algorithm>
#include <vector>
#define INF 987654321
using namespace std;
int N, M;
int global_Answer = -INF;
vector<pair<intint> > virus_pos;
vector<vector<int> > map;
bool start_next = false;
struct dir{
    int dr, dc;
};
dir direction[4= { { 01 }, { 0-1 }, { 10 }, { -10 } };
 
void dfs(int r, int c, int installed){
    if (installed == 3){
        queue<pair<intint> > q;
        vector<vector<bool> > check;
        check.assign(N, vector<bool>(M, false));
        for (int i = 0; i < virus_pos.size(); i++){
            int cur_r = virus_pos[i].first, cur_c = virus_pos[i].second;
            check[cur_r][cur_c] = true;
            q.push(make_pair(cur_r, cur_c));
        }
        while (!q.empty()){
            int f_r = q.front().first;
            int f_c = q.front().second;
            q.pop();
            for (int i = 0; i < 4; i++){
                int n_r = f_r + direction[i].dr;
                int n_c = f_c + direction[i].dc;
                if (n_r >= 0 && n_r < N && n_c >= 0 && n_c < M){
                    if (!check[n_r][n_c] && map[n_r][n_c] == 0){
                        check[n_r][n_c] = true;
                        q.push(make_pair(n_r, n_c));
                    }
                }
            }
        }
        int local_Answer = 0;
        for (int i = 0; i < N; i++){
            for (int j = 0; j < M; j++){
                if (!check[i][j] && map[i][j] == 0)
                    local_Answer++;
            }
        }
        global_Answer = max(global_Answer, local_Answer);
        return;
    }
    for (int i = 0; i < N; i++){
        for (int j = 0; j < M; j++){
            if (i > r || (r == i && j > c)){
                if (map[i][j] == 0){
                    map[i][j] = 1;
                    dfs(i, j, installed + 1);
                    map[i][j] = 0;
                }
            }
        }
    }
}
 
int main(){
    ios_base::sync_with_stdio(0);
    cout.tie(0);
    cin.tie(0);
 
    cin >> N >> M;
    map.assign(N, vector<int>(M, 0));
    for (int i = 0; i < N; i++){
        for (int j = 0; j < M; j++){
            cin >> map[i][j];
            if (map[i][j] == 2)
                virus_pos.push_back(make_pair(i, j));
        }
    }
    dfs(-1-10);
    cout << global_Answer << '\n';
    return 0;
}
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter
http://colorscripter.com/info#e" target="_blank" style="text-decoration:none;color:white">cs

 

2. 브루트포스 (52ms)

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
#include <iostream>
#include <algorithm>
#include <vector>
#include <deque>
#define INF 987654321
 
using namespace std;
 
typedef struct dir{
    int dr, dc;
}dir;
dir direction[4= { { 01 }, { 0-1 }, { 10 }, { -10 } };
int global_answer = -INF;
int N, M;
deque<pair<intint> > dq;
 
vector<vector<bool> > check; // 
vector<vector<int> > map, map_cpy; // map 고정. map_cpy 매번 map으로 재초기화.
 
vector<pair<intint> > virus, blank;
// blank 원소 수만큼 flag 선언한 뒤, 그 중 3개만 1로, 나머지 0으로 설정.
vector<int> flag;
 
void reset(){
    dq.clear();
    for (int i = 0; i < N; i++){
        for (int j = 0; j < M; j++){
            map_cpy[i][j] = map[i][j];
            check[i][j] = false;
        }
    }
    for (int i = 0; i < virus.size(); i++){
        int cur_r = virus[i].first;
        int cur_c = virus[i].second;
        check[cur_r][cur_c] = true;
        dq.push_back(make_pair(cur_r, cur_c));
    }
}
int main(){
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
 
    cin >> N >> M;
    check.assign(N, vector<bool>(M, false));
    map.assign(N, vector<int>(M, 0));
    map_cpy.assign(N, vector<int>(M, 0));
    for (int i = 0; i < N; i++){
        for (int j = 0; j < M; j++){
            cin >> map[i][j];
            map_cpy[i][j] = map[i][j];
            if (map[i][j] == 0){
                blank.push_back(make_pair(i, j));
            }
            else if (map[i][j] == 2){
                virus.push_back(make_pair(i, j));
            }
        }
    }
 
    flag.assign(blank.size(), 0);
    for (int i = 0; i < 3; i++)
        flag[i] = 1;
    sort(flag.begin(), flag.end());
 
    do{
        reset(); // 바이러스 체크, 지도 초기화.
 
        int local_answer = 0;
        for (int i = 0; i < flag.size(); i++){
            if (flag[i]){
                //i번째 blank 당첨~
                int towall_r = blank[i].first;
                int towall_c = blank[i].second;
                map_cpy[towall_r][towall_c] = 1;
            }
        }
        // 지도에 새로운 1 지정 완료. check 완료. 
        while (!dq.empty()){
            int cur_r = dq.front().first;
            int cur_c = dq.front().second;
            dq.pop_front();
            for (int i = 0; i < 4; i++){
                int nr = cur_r + direction[i].dr;
                int nc = cur_c + direction[i].dc;
                if (nr >= 0 && nr < N && nc >= 0 && nc < M){
                    if (!check[nr][nc] && map_cpy[nr][nc] == 0){
                        // 내부, 방문x, 빈 공간이면 방문.
                        check[nr][nc] = true;
                        dq.push_back(make_pair(nr, nc));
                    }
                }
            }
        }
 
        for (int i = 0; i < N; i++){
            for (int j = 0; j < M; j++){
                if (map_cpy[i][j] == 0 && !check[i][j]){
                    local_answer++;
                }
            }
        }
        global_answer = max(global_answer, local_answer);
    } while (next_permutation(flag.begin(), flag.end()));
    cout << global_answer << '\n';
    return 0;
}
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter
http://colorscripter.com/info#e" target="_blank" style="text-decoration:none;color:white">cs

백트래킹 관련 문제를 좀 더 풀어봐야 겠다.


Comments