본문 바로가기
CS/Algorithm

[알고리즘][DFS][14502] 연구소

by 별토끼. 2018. 4. 25.
반응형

[알고리즘][DFS][14502] 연구소


문제

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



풀이

0은 공간, 1은 벽, 2는 바이러스입니다. n×m의 배열을 만들어 0,1,2로 입력받은 뒤 추가로 1인 벽을 3개 만들 수 있습니다. 추가적으로 세운 벽까지 포함하여 바이러스가 퍼지지 않는 안전영역의 최댓값을 구하면 됩니다. 


이 때, 어디에 벽을 세우느냐가 가장 큰 관건입니다. 벽 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
112
113
114
115
116
117
118
119
120
package algorithm_DFS;
 
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
/* 삼성 SW 역량 테스트 기출 */
public class q_14502 {
    static int n;
    static int m;
    static int ans;
    static int[][] arr;
    static int[][] map = new int[9][9];
    static int dx[] = {1-100};
    static int dy[] = {001-1};
    
    public static class wall_n{
        int x, y;
        public wall_n(int x, int y) {
            this.x = x;
            this.y = y;
        }
    }    
    
    public static void make_map() {
        for(int i=0;i<n;i++) {
            for(int j=0;j<m;j++) {
                map[i][j] = arr[i][j];
            }
        }
    }
    public static void make_wall(int cnt) {
        //벽을 3개 세웠다면 바이러스를 퍼뜨려 count한다.
        if(cnt==3) {
            virus();
            return;
        }
        for(int i=0;i<n;i++) {
            for(int j=0;j<m;j++) {
                if(map[i][j]==1||map[i][j]==2continue;
                map[i][j]=1;
                make_wall(cnt+1);
                map[i][j]=0//backtracking
            }
        }
    }
    //바이러스 퍼뜨리기
    public static void virus() {
        int[][] temp = new int[n][m]; // 임시 배열을 만들어 바이러스를 퍼뜨려본다.
        for(int i=0;i<n;i++) {
            for(int j=0;j<m;j++) {
                temp[i][j] = map[i][j];
            }
        }
        Queue<wall_n> q = new LinkedList<>();
        for(int i=0;i<n;i++) {
            for(int j=0;j<m;j++) {
                if(temp[i][j]==2) {
                    q.add(new wall_n(i,j));
                }
            }
        }
        
        while(!q.isEmpty()) {
            wall_n now = q.remove();
            int x = now.x;
            int y = now.y;
            for(int i=0;i<4;i++) {
                int nx = x + dx[i];
                int ny = y + dy[i];
                if(nx<0 || nx>=|| ny<0 || ny>=m) continue;
                if(temp[nx][ny]==2 || temp[nx][ny]==1continue;
                temp[nx][ny]=2;
                q.add(new wall_n(nx, ny));
            }
        }
        
        //감염안된 지역 counting
        int cnt = 0;
        for(int i=0;i<n;i++) {
            for(int j=0;j<m;j++) {
                if(temp[i][j]==0++cnt;
            }
        }
        ans = Math.max(ans, cnt);
    }
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        /*
         * 1. 연구소의 크기를 받는다. (n,m)
         * 2. nxm의 행렬을 입력받는다.
         * 3. 가능한 위쳉 벽 3개를 배치(dfs, backtracking)
         * 4. 바이러스를 퍼뜨린다.(dfs)
         * 5. 행렬의 0의 갯수를 counting 한다.
         */
        n = scan.nextInt();
        m = scan.nextInt();
        scan.nextLine();
        
        arr = new int[n][m];
        
        for(int i=0;i<n;i++) {
            for(int j=0;j<m;j++) {
                arr[i][j] = scan.nextInt();
            }
        }
        for(int i=0;i<n;i++) {
            for(int j=0;j<m;j++) {
                if(arr[i][j]==2 || arr[i][j]==1continue;
                make_map(); //벽이나 바이러스가 아닐경우 
                map[i][j]=1;
                make_wall(1);
                map[i][j]=0;
            }
        }
        System.out.println(ans);
    }
 
 
}
 
cs


반응형

댓글