문제

방향그래프가 주어지면 주어진 시작점에서 다른 모든 정점으로의 최단 경로를 구하는 프로그램을 작성하시오. 단, 모든 간선의 가중치는 10 이하의 자연수이다.

 

 

입력

첫째 줄에 정점의 개수 V와 간선의 개수 E가 주어진다. (1≤V≤20,000, 1≤E≤300,000) 모든 정점에는 1부터 V까지 번호가 매겨져 있다고 가정한다. 둘째 줄에는 시작 정점의 번호 K(1≤K≤V)가 주어진다. 셋째 줄부터 E개의 줄에 걸쳐 각 간선을 나타내는 세 개의 정수 (u, v, w)가 순서대로 주어진다. 이는 u에서 v로 가는 가중치 w인 간선이 존재한다는 뜻이다. u와 v는 서로 다르며 w는 10 이하의 자연수이다. 서로 다른 두 정점 사이에 여러 개의 간선이 존재할 수도 있음에 유의한다.

 

 

출력

첫째 줄부터 V개의 줄에 걸쳐, i번째 줄에 i번 정점으로의 최단 경로의 경로값을 출력한다. 시작점 자신은 0으로 출력하고, 경로가 존재하지 않는 경우에는 INF를 출력하면 된다.

 

 

예제

 

코드

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
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.StringTokenizer;
 
public class Main_BJ_1753_최단경로 {
    
    public static class Node{
        int v,w;
 
        public Node(int v, int w) {
            this.v = v;
            this.w = w;
        }
    }
    
    static int V,E,K, INFINITY = Integer.MAX_VALUE;
    static boolean []visited;
    static List<Node> list[];
    static int [] distance;
 
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringBuilder sb = new StringBuilder();
        StringTokenizer st;
        
        st = new StringTokenizer(br.readLine()," ");
        
        V = Integer.parseInt(st.nextToken());
        E = Integer.parseInt(st.nextToken());
        K = Integer.parseInt(br.readLine());
        
        list =new ArrayList[V+1];
        distance = new int[V+1];
        visited = new boolean[V+1];
        
        for(int i=1;i<V+1;i++) list[i]= new ArrayList<>();
        
        for(int i=0;i<E;i++) {
            st = new StringTokenizer(br.readLine()," ");
            int u = Integer.parseInt(st.nextToken());
            int v = Integer.parseInt(st.nextToken());
            int w = Integer.parseInt(st.nextToken());
            
            list[u].add(new Node(v,w));
        }
        
        Arrays.fill(distance, INFINITY);
        distance[K] = 0;
        
        int min, current = 0;
        for(int i=0; i<V;i++) {
            min = Integer.MAX_VALUE;
            current = -1;
            for(int j=1;j<V+1;j++) {
                if(!visited[j] && distance[j]<min) {
                    min = distance[j];
                    current =j;
                }
            }
            if(current == -1) break;
            
            for(Node next : list[current]) {
                if(!visited[next.v] && distance[next.v]> distance[current]+next.w) {
                    distance[next.v] = distance[current] + next.w;
                }
            }
            visited[current] = true;
        }
        
        for(int i=1;i<V+1;i++) {
            if(distance[i]==INFINITY) sb.append("INF\n");
            else sb.append(distance[i]+"\n");
        }
        System.out.println(sb.toString());
    }
}
 
cs

 

 

 

 

'문제 > 백준' 카테고리의 다른 글

백준 14502번 연구소 [JAVA]  (0) 2021.03.26
백준 2206번 벽 부수고 이동하기 [JAVA]  (0) 2021.03.26
백준 3036번 링 [JAVA]  (0) 2021.03.25
백준 2665번 미로만들기 [JAVA]  (0) 2021.03.25
백준 5427번 불 [JAVA]  (0) 2021.03.25

문제

상근이는 창고에서 링 N개를 발견했다. 상근이는 각각의 링이 앞에 있는 링과 뒤에 있는 링과 접하도록 바닥에 내려놓았다.

상근이는 첫 번째 링을 돌리기 시작했고, 나머지 링도 같이 돌아간다는 사실을 발견했다. 나머지 링은 첫 번째 링 보다 빠르게 돌아가기도 했고, 느리게 돌아가기도 했다. 이렇게 링을 돌리다 보니 첫 번째 링을 한 바퀴 돌리면, 나머지 링은 몇 바퀴 도는지 궁금해졌다.

링의 반지름이 주어진다. 이때, 첫 번째 링을 한 바퀴 돌리면, 나머지 링은 몇 바퀴 돌아가는지 구하는 프로그램을 작성하시오.

 

 

입력

첫째 줄에 링의 개수 N이 주어진다. (3 ≤ N ≤ 100)

다음 줄에는 링의 반지름이 상근이가 바닥에 놓은 순서대로 주어진다. 반지름은 1과 1000를 포함하는 사이의 자연수이다.

 

 

출력

출력은 총 N-1줄을 해야 한다. 첫 번째 링을 제외한 각각의 링에 대해서, 첫 번째 링을 한 바퀴 돌리면 그 링은 몇 바퀴 도는지 기약 분수 형태 A/B로 출력한다.

 

 

예제

코드

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
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
 
public class Main_BJ_3036_링 {
 
    public static void main(String[] args) throws NumberFormatException, IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;
        StringBuilder sb = new StringBuilder();
        
        int N = Integer.parseInt(br.readLine());
        int [] arr = new int[N];
        
        st = new StringTokenizer(br.readLine()," ");
        for(int i=0;i<N;i++) {
            arr[i] = Integer.parseInt(st.nextToken());
        }
        
        int ring = arr[0];
        for(int i=1;i<N;i++) {
            int num = ea(ring,arr[i]);
            sb.append(ring/num+"/"+arr[i]/num+"\n");
        }
        System.out.println(sb.toString());
 
 
    }
    
    public static int ea(int x , int y) {
        if(y==0return x;
        else return ea(y, x%y);
    }
 
}
cs

 

 

풀이방법

첫 번째 링을 한 바퀴 돌리면, 나머지 링은 몇 바퀴 돌아가는지 구하는 문제였습니다. 저는 첫 번째 링과 해당 링의 최대 공배수를 구해 각각 최대 공약수로 나눠주는 방법으로 구현했습니다.

 

문제

n×n 바둑판 모양으로 총 n2개의 방이 있다. 일부분은 검은 방이고 나머지는 모두 흰 방이다. 검은 방은 사면이 벽으로 싸여 있어 들어갈 수 없다. 서로 붙어 있는 두 개의 흰 방 사이에는 문이 있어서 지나다닐 수 있다. 윗줄 맨 왼쪽 방은 시작 방으로서 항상 흰 방이고, 아랫줄 맨 오른쪽 방은 끝방으로서 역시 흰 방이다.

시작 방에서 출발하여 길을 찾아서 끝방으로 가는 것이 목적인데, 아래 그림의 경우에는 시작 방에서 끝 방으로 갈 수가 없다. 부득이 검은 방 몇 개를 흰 방으로 바꾸어야 하는데 되도록 적은 수의 방의 색을 바꾸고 싶다.

아래 그림은 n=8인 경우의 한 예이다.

위 그림에서는 두 개의 검은 방(예를 들어 (4,4)의 방과 (7,8)의 방)을 흰 방으로 바꾸면, 시작 방에서 끝방으로 갈 수 있지만, 어느 검은 방 하나만을 흰 방으로 바꾸어서는 불가능하다. 검은 방에서 흰 방으로 바꾸어야 할 최소의 수를 구하는 프로그램을 작성하시오.

단, 검은 방을 하나도 흰방으로 바꾸지 않아도 되는 경우는 0이 답이다.

 

 

입력

첫 줄에는 한 줄에 들어가는 방의 수 n(1≤n≤50)이 주어지고, 다음 n개의 줄의 각 줄마다 0과 1이 이루어진 길이가 n인 수열이 주어진다. 0은 검은 방, 1은 흰 방을 나타낸다.

 

 

출력

첫 줄에 흰 방으로 바꾸어야 할 최소의 검은 방의 수를 출력한다.

 

 

예제

 

코드

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
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Comparator;
import java.util.PriorityQueue;
 
public class Main_BJ_2665_미로만들기 {
    static int [][] map;
    static int n, ans;
    static boolean [][] visited;
    static int [] dx = {-1,0,1,0};
    static int [] dy = {0,1,0,-1};
 
    public static void main(String[] args) throws NumberFormatException, IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        
        n = Integer.parseInt(br.readLine());
        
        map = new int[n][n];
        visited = new boolean[n][n];
        for(int i=0;i<n;i++) {
            String str = br.readLine();
            for(int j =0;j<n;j++) {
                map[i][j] = str.charAt(j)-48;
            }
        }
        bfs();
        System.out.println(ans);
    }
    
    public static void bfs() {
        PriorityQueue<int[]> pq = new PriorityQueue<>(new Comparator<int[]>() {
 
            @Override
            public int compare(int[] o1, int[] o2) {
                // TODO Auto-generated method stub
                return o1[2]-o2[2];
            }
        });
        
        visited[0][0]= true;
        
        pq.offer(new int[] {0,0,0});
        
        while(!pq.isEmpty()) {
            int [] temp = pq.poll();
            
            if(temp[0]==n-1 && temp[1]==n-1) {
                ans = temp[2];
                return;
            }
            
            for(int i=0;i<4;i++) {
                int nx = temp[0]+dx[i];
                int ny = temp[1]+dy[i];
                
                if(range(nx,ny) && !visited[nx][ny]) {
                    visited[nx][ny]= true;
                    if(map[nx][ny]==1) pq.offer(new int[] {nx,ny,temp[2]});
                    else pq.offer(new int[] {nx,ny, temp[2]+1});
                    
                }
            }    
        }    
    }
    
    public static boolean range(int x, int y) {
        return x>=0 && y>=0 && x<&& y<n;
    }
}
cs

 

 

풀이방법

(1,1)에서 (N, N)으로 가야 하는데 검은 방은 들어갈 수 없으므로 흰 방으로만 들어갈 수 있다. 만약 시작 방에서 끝 방으로 갈 수 없을 경우에는 검은 방을 흰방으로 바꿀 수 있다. 시작방에서 끝 방으로 갈 때 흰 방으로 바꾸어야 할 최소의 검은 방 수를 구하는 문제였습니다. 시작 위치인 (0,0)를 우선순위 큐에 넣어두고 상하좌우 탐색을 시작해 이동했습니다. 만약 이동하다가 해당 위치가 검은 방일 경우에는 벽을 부수고 이동하고 흰 방인 경우에는 그냥 이동하는 정보를 우선순위 큐에 넣어주었습니다. 우선순위 큐에는 벽을 부슨 횟수를 정렬하고 있으므로 큐의 맨 앞에 값이 가장 적은 수의 검은 방을 부수면서 도착지점까지 간 정보를 담고 있으므로 만약 해당 위치 값이 도착지일 때의 벽을 부순 횟수를 리턴해주었습니다.

 

 

 

 

'문제 > 백준' 카테고리의 다른 글

백준 1753번 최단경로 [JAVA]  (0) 2021.03.25
백준 3036번 링 [JAVA]  (0) 2021.03.25
백준 5427번 불 [JAVA]  (0) 2021.03.25
백준 1261번 알고번 알고스팟 [JAVA]  (0) 2021.03.24
백준 2636번 치즈 [JAVA]  (0) 2021.03.24

문제

상근이는 빈 공간과 벽으로 이루어진 건물에 갇혀있다. 건물의 일부에는 불이 났고, 상근이는 출구를 향해 뛰고 있다.

매 초마다, 불은 동서남북 방향으로 인접한 빈 공간으로 퍼져나간다. 벽에는 불이 붙지 않는다. 상근이는 동서남북 인접한 칸으로 이동할 수 있으며, 1초가 걸린다. 상근이는 벽을 통과할 수 없고, 불이 옮겨진 칸 또는 이제 불이 붙으려는 칸으로 이동할 수 없다. 상근이가 있는 칸에 불이 옮겨옴과 동시에 다른 칸으로 이동할 수 있다.

빌딩의 지도가 주어졌을 때, 얼마나 빨리 빌딩을 탈출할 수 있는지 구하는 프로그램을 작성하시오.

 

 

입력

첫째 줄에 테스트 케이스의 개수가 주어진다. 테스트 케이스는 최대 100개이다.

각 테스트 케이스의 첫째 줄에는 빌딩 지도의 너비와 높이 w와 h가 주어진다. (1 ≤ w, h ≤ 1000)

다음 h개 줄에는 w개의 문자, 빌딩의 지도가 주어진다.

  • '.': 빈 공간
  • '#': 벽
  • '@': 상근이의 시작 위치
  • '*': 불

각 지도에 @의 개수는 하나이다.

 

 

출력

각 테스트 케이스마다 빌딩을 탈출하는데 가장 빠른 시간을 출력한다. 빌딩을 탈출할 수 없는 경우에는 "IMPOSSIBLE"을 출력한다.

 

 

예제

 

 

코드

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
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;
 
public class Main_BJ_5427_불 {
    
    static class info{
        int x, y , time;
 
        public info(int x, int y, int time) {
            this.x = x;
            this.y = y;
            this.time = time;
        }
    }
    
    static char [][]map;
    static int w,h, answer;
    static boolean [][] visited;
    static Queue<info> fire;
    static Queue<info> person;
    static int [] dx = {-1,0,1,0}; 
    static int [] dy = {0,1,0,-1};
 
 
    public static void main(String[] args) throws NumberFormatException, IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringBuilder sb = new StringBuilder();
        StringTokenizer st;
        
        int T = Integer.parseInt(br.readLine());
        
        for(int tc=0;tc<T;tc++) {
            st = new StringTokenizer(br.readLine()," ");
            w = Integer.parseInt(st.nextToken());
            h = Integer.parseInt(st.nextToken());
            
            map = new char[h][w];
            visited = new boolean[h][w];
            
            fire = new LinkedList<>();
            person = new LinkedList<>();
            
            for(int i=0;i<h;i++) {
                String str = br.readLine();
                for(int j=0;j<w;j++) {
                    map[i][j]= str.charAt(j);
                    if(map[i][j]=='@') person.offer(new info(i,j,0));
                    else if(map[i][j]=='*') fire.offer(new info(i,j,0));
                }
            }
            
            answer =0;
            bfs();
            if(answer==0) sb.append("IMPOSSIBLE\n");
            else sb.append(answer+"\n");
        }
        System.out.println(sb.toString());
    }
    
    public static void bfs() {
        
        
        while(!person.isEmpty()) {
            int size = fire.size();
            for(int i=0;i<size;i++) {
                info temp = fire.poll();
                for(int d=0;d<4;d++) {
                    int nx = temp.x+dx[d];
                    int ny = temp.y+dy[d];
 
                    if(range(nx,ny) && (map[nx][ny]=='.' || map[nx][ny]=='@')){
                        map[nx][ny]='*';
                        fire.offer(new info(nx,ny,0));
                    }
                }
            }
            
            size = person.size();
            for(int i=0;i<size;i++) {
                info temp = person.poll();
                for(int d=0;d<4;d++) {
                    int nx = temp.x+dx[d];
                    int ny = temp.y+dy[d];
                    
                    if(!range(nx,ny)) {
                        answer = temp.time+1;
                        return;
                    }
                    
                    if(map[nx][ny]=='.'){
                        map[nx][ny]='@';
                        person.offer(new info(nx,ny,temp.time+1));
                    }
                    
                }
            }
        }    
    }
    
    public static boolean range(int x, int y) {
        return x>=0 && y>=0 && x<&& y<w;
    }
 
}
cs

 

 

풀이 방법

빌딩의 지도가 주어졌을 때, 상근이가 얼마나 빨리 빌딩을 탈출할 수 있는지 구하는 문제였습니다.

저는 상근이 위치정보를 person큐와 불의 위치정보를 fire큐에 넣어주었습니다.

불과 상근이는 동시에 움직이므로 bfs를 이용해 불을 먼저 움직인 뒤, 상근이를 움직였습니다. 만약 상근이가 다음 움직일 위치가 배열의 범위를 넘어선다면 출구로 빠져나간 것이므로 리턴을 통해 걸린 시간을 반환해주었습니다.

 

 

'문제 > 백준' 카테고리의 다른 글

백준 3036번 링 [JAVA]  (0) 2021.03.25
백준 2665번 미로만들기 [JAVA]  (0) 2021.03.25
백준 1261번 알고번 알고스팟 [JAVA]  (0) 2021.03.24
백준 2636번 치즈 [JAVA]  (0) 2021.03.24
백준 18405번 경제적 전염 [JAVA]  (0) 2021.03.23

문제

알고스팟 운영진이 모두 미로에 갇혔다. 미로는 N*M 크기이며, 총 1*1크기의 방으로 이루어져 있다. 미로는 빈 방 또는 벽으로 이루어져 있고, 빈 방은 자유롭게 다닐 수 있지만, 벽은 부수지 않으면 이동할 수 없다.

알고스팟 운영진은 여러명이지만, 항상 모두 같은 방에 있어야 한다. 즉, 여러 명이 다른 방에 있을 수는 없다. 어떤 방에서 이동할 수 있는 방은 상하좌우로 인접한 빈 방이다. 즉, 현재 운영진이 (x, y)에 있을 때, 이동할 수 있는 방은 (x+1, y), (x, y+1), (x-1, y), (x, y-1) 이다. 단, 미로의 밖으로 이동 할 수는 없다.

벽은 평소에는 이동할 수 없지만, 알고스팟의 무기 AOJ를 이용해 벽을 부수어 버릴 수 있다. 벽을 부수면, 빈 방과 동일한 방으로 변한다.

만약 이 문제가 알고스팟에 있다면, 운영진들은 궁극의 무기 sudo를 이용해 벽을 한 번에 다 없애버릴 수 있지만, 안타깝게도 이 문제는 Baekjoon Online Judge에 수록되어 있기 때문에, sudo를 사용할 수 없다.

현재 (1, 1)에 있는 알고스팟 운영진이 (N, M)으로 이동하려면 벽을 최소 몇 개 부수어야 하는지 구하는 프로그램을 작성하시오.

 

 

입력

첫째 줄에 미로의 크기를 나타내는 가로 크기 M, 세로 크기 N (1 ≤ N, M ≤ 100)이 주어진다. 다음 N개의 줄에는 미로의 상태를 나타내는 숫자 0과 1이 주어진다. 0은 빈 방을 의미하고, 1은 벽을 의미한다.

(1, 1)과 (N, M)은 항상 뚫려있다.

 

 

출력

첫째 줄에 알고스팟 운영진이 (N, M)으로 이동하기 위해 벽을 최소 몇 개 부수어야 하는지 출력한다.

 

 

예제

 

코드

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
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.StringTokenizer;
 
public class Main_BJ_1261_알고스팟 {
    static int [][] map;
    static boolean [][] visited;
    static int [] dx= {-1,0,1,0};
    static int [] dy= {0,1,0,-1};
    static int N,M;
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;
        
        st = new StringTokenizer(br.readLine()," ");
        
        N = Integer.parseInt(st.nextToken());
        M = Integer.parseInt(st.nextToken());
        
        map = new int[M][N];
        visited = new boolean[M][N];
        
        for(int i=0;i<M;i++) {
            String str = br.readLine();
            for(int j=0;j<N;j++) map[i][j] = str.charAt(j)-48;
        }
        
        int result = bfs();
        System.out.println(result);
 
    }
    
    public static int bfs() {
        PriorityQueue<int []> queue = new PriorityQueue<>(new Comparator<int []>() {
 
            @Override
            public int compare(int[] o1, int[] o2) {
                return o1[2]-o2[2];
            }
        });
        
        queue.add(new int[]{0,0,0});
        visited[0][0]= true;
        
        while(!queue.isEmpty()) {
            int [] temp = queue.poll();
            int x = temp[0];
            int y = temp[1];
            int cnt = temp[2];
            if(x==M-1 && y==N-1) {
                return cnt;
            }
            for(int i=0;i<4;i++) {
                int nx = x+dx[i];
                int ny = y+dy[i];
                
                if(range(nx,ny) && !visited[nx][ny]) {
                    visited[nx][ny] = true;
                    if(map[nx][ny]==1) queue.offer(new int[] {nx,ny,cnt+1});
                    else queue.offer(new int[] {nx,ny,cnt});
                }
            }
        }
        return 0;
    }
    
    public static boolean range(int x, int y) {
        return x>=0 && y>=0 && x<&& y<N;
    }
 
}
cs

 

 

풀이 방법

미로의 가장 왼쪽 위인(0,0)에서 가장 오른쪽 아래(M-1, N-1)의 위치로 이동하기 위해 최소한으로 몇 개의 벽을 부수는지 알아내는 문제였습니다. 저는 bfs()를 사용해서 구현했습니다. 먼저 시작점인 (0,0)과 함께 벽을 부슨 개수를 기억하기 위해 벽을 부순 횟수인 cnt와 함께 우선순위 큐에 저장해주었습니다. 우선순위 큐를 사용한 이유는 가장 적은 수의 벽을 부순 개수를 찾아야 하기 때문에 우선순위 큐를 이용하여 cnt값이 가장 작은 것을 기준으로 진행하였습니다. 만약 도착점인 (M-1, N-1)에 도착했다면 도착지까지의 벽을 부순 횟수인 cnt 값을 리턴해 주었습니다.

 

 

 

'문제 > 백준' 카테고리의 다른 글

백준 2665번 미로만들기 [JAVA]  (0) 2021.03.25
백준 5427번 불 [JAVA]  (0) 2021.03.25
백준 2636번 치즈 [JAVA]  (0) 2021.03.24
백준 18405번 경제적 전염 [JAVA]  (0) 2021.03.23
백준 1966번 프린터 큐 [JAVA]  (0) 2021.03.23

문제

아래 <그림 1>과 같이 정사각형 칸들로 이루어진 사각형 모양의 판이 있고, 그 위에 얇은 치즈(회색으로 표시된 부분)가 놓여 있다. 판의 가장자리(<그림 1>에서 네모 칸에 X친 부분)에는 치즈가 놓여 있지 않으며 치즈에는 하나 이상의 구멍이 있을 수 있다.

이 치즈를 공기 중에 놓으면 녹게 되는데 공기와 접촉된 칸은 한 시간이 지나면 녹아 없어진다. 치즈의 구멍 속에는 공기가 없지만 구멍을 둘러싼 치즈가 녹아서 구멍이 열리면 구멍 속으로 공기가 들어가게 된다. <그림 1>의 경우, 치즈의 구멍을 둘러싼 치즈는 녹지 않고 ‘c’로 표시된 부분만 한 시간 후에 녹아 없어져서 <그림 2>와 같이 된다.

다시 한 시간 후에는 <그림 2>에서 ‘c’로 표시된 부분이 녹아 없어져서 <그림 3>과 같이 된다.

<그림 3>은 원래 치즈의 두 시간 후 모양을 나타내고 있으며, 남은 조각들은 한 시간이 더 지나면 모두 녹아 없어진다. 그러므로 처음 치즈가 모두 녹아 없어지는 데는 세 시간이 걸린다. <그림 3>과 같이 치즈가 녹는 과정에서 여러 조각으로 나누어질 수도 있다.

입력으로 사각형 모양의 판의 크기와 한 조각의 치즈가 판 위에 주어졌을 때, 공기 중에서 치즈가 모두 녹아 없어지는 데 걸리는 시간과 모두 녹기 한 시간 전에 남아있는 치즈 조각이 놓여 있는 칸의 개수를 구하는 프로그램을 작성하시오.

 

 

 

입력

첫째 줄에는 사각형 모양 판의 세로와 가로의 길이가 양의 정수로 주어진다. 세로와 가로의 길이는 최대 100이다. 판의 각 가로줄의 모양이 윗 줄부터 차례로 둘째 줄부터 마지막 줄까지 주어진다. 치즈가 없는 칸은 0, 치즈가 있는 칸은 1로 주어지며 각 숫자 사이에는 빈칸이 하나씩 있다.

 

 

 

출력

첫째 줄에는 치즈가 모두 녹아서 없어지는 데 걸리는 시간을 출력하고, 둘째 줄에는 모두 녹기 한 시간 전에 남아있는 치즈조각이 놓여 있는 칸의 개수를 출력한다.

 

 

 

예제

 

 

코드

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
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
 
public class Main_BJ_2636_치즈 {
    static int N,M, cheese;
    static int [][] map;
    static boolean [][] visited;
    static int dx[] = {-1,0,1,0};
    static int dy[] = {0,1,0,-1};
 
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;
        
        st = new StringTokenizer(br.readLine()," ");
        
        N = Integer.parseInt(st.nextToken());
        M = Integer.parseInt(st.nextToken());
        
        map = new int[N][M];
        
        for(int i=0;i<N;i++) {
            st = new StringTokenizer(br.readLine()," ");
            for(int j=0;j<M;j++) {
                map[i][j]=Integer.parseInt(st.nextToken());
            }
        }
        
        int time=1;
        while(true) {
            visited = new boolean[N][M];
            cheese=0;
            visited[0][0]=true;
            dfs(0,0);
            
            if(!check()) break;
            time++;
        }
        System.out.println(time+"\n"+cheese);
 
    }
    
    public static void dfs(int x, int y) {
        
        for(int i=0;i<4;i++) {
            int nx = x + dx[i];
            int ny = y + dy[i];
            
            if(range(nx,ny) && !visited[nx][ny]) {
                visited[nx][ny]=true;
                
                if(map[nx][ny]==0) dfs(nx,ny);
                else {
                    map[nx][ny]=2; cheese++;
                }
            }
        }
    }
    
    public static boolean range(int x, int y) {
        return x>=0 && y>=0 && x<&& y<M;
    }
    
    public static boolean check() {
        
        int count=0;
        for(int i=0;i<N;i++) {
            for(int j=0;j<M;j++) {
                if(map[i][j]==2) map[i][j]=0;
                else if(map[i][j]==1) count++;
            }
        }
        
        if(count==0return false;
        else return true;
    }
 
}
cs

 

 

풀이 방법

치즈가 모두 녹아서 없어지는 데 걸리는 시간과, 치즈가 모두 녹기 한 시간 전에 남아있는 치즈 조각이 놓여 있는 칸의 개수를 구하는 문제였습니다.

 

저는 DFS를 이용해 문제를 풀었습니다. 여기서 주의할 점은 치즈의 구멍을 둘러싼 치즈는 녹지 않는다는 점입니다!

공기 중에 치즈를 놓으면 1초 뒤 그 치즈는 사라지게 됩니다. 저는 공기를 기준으로 상, 하, 좌, 우에 치즈가 있다면 그 치즈 자리를 2로 변경해주었습니다. 여기서 치즈 자리를 0이 아닌 2로 변경해주는 이유는 만약 바로 0으로 바꿔줬더라면 그 치즈 자리가 0이 되어 그 자리에서 상, 하, 좌, 우 에 있는 치즈 또한 공기 중에 놓여있어 사라지기 때문입니다. 그래서 dfs() 메서드를 통해 공기와 접촉한 치즈들의 자리를 2로 변경해준 뒤, check() 함수를 통해 위치의 값이 2인 곳을 0으로 바꿔주고 map에 치즈가 남아있는지 확인해주었습니다. 만약 치즈가 남아있지 않다면 반복문을 종료해 치즈가 모두 녹아서 없어지는 데 걸리는 시간과, 모두 녹기 한 시간 전에 남아있는 치즈 조각의 수를 출력해주었습니다.

 

 

'문제 > 백준' 카테고리의 다른 글

백준 5427번 불 [JAVA]  (0) 2021.03.25
백준 1261번 알고번 알고스팟 [JAVA]  (0) 2021.03.24
백준 18405번 경제적 전염 [JAVA]  (0) 2021.03.23
백준 1966번 프린터 큐 [JAVA]  (0) 2021.03.23
백준 7568번 덩치 [JAVA]  (0) 2021.03.23

문제

NxN 크기의 시험관이 있다. 시험관은 1x1 크기의 칸으로 나누어지며, 특정한 위치에는 바이러스가 존재할 수 있다. 모든 바이러스는 1번부터 K번까지의 바이러스 종류 중 하나에 속한다.

시험관에 존재하는 모든 바이러스는 1초마다 상, 하, 좌, 우의 방향으로 증식해 나간다. 단, 매 초마다 번호가 낮은 종류의 바이러스부터 먼저 증식한다. 또한 증식 과정에서 특정한 칸에 이미 어떠한 바이러스가 존재한다면, 그곳에는 다른 바이러스가 들어갈 수 없다.

시험관의 크기와 바이러스의 위치 정보가 주어졌을 때, S초가 지난 후에 (X,Y)에 존재하는 바이러스의 종류를 출력하는 프로그램을 작성하시오. 만약 S초가 지난 후에 해당 위치에 바이러스가 존재하지 않는다면, 0을 출력한다. 이때 X와 Y는 각각 행과 열의 위치를 의미하며, 시험관의 가장 왼쪽 위에 해당하는 곳은 (1,1)에 해당한다.

예를 들어 다음과 같이 3x3 크기의 시험관이 있다고 하자. 서로 다른 1번, 2번, 3번 바이러스가 각각 (1,1), (1,3), (3,1)에 위치해 있다. 이때 2초가 지난 뒤에 (3,2)에 존재하는 바이러스의 종류를 계산해보자.

1초가 지난 후에 시험관의 상태는 다음과 같다.

2초가 지난 후에 시험관의 상태는 다음과 같다.

결과적으로 2초가 지난 뒤에 (3,2)에 존재하는 바이러스의 종류는 3번 바이러스다. 따라서 3을 출력하면 정답이다.

 

 

 

입력

첫째 줄에 자연수 N, K가 공백을 기준으로 구분되어 주어진다. (1 ≤ N ≤ 200, 1 ≤ K ≤ 1,000) 둘째 줄부터 N개의 줄에 걸쳐서 시험관의 정보가 주어진다. 각 행은 N개의 원소로 구성되며, 해당 위치에 존재하는 바이러스의 번호가 공백을 기준으로 구분되어 주어진다. 단, 해당 위치에 바이러스가 존재하지 않는 경우 0이 주어진다. 또한 모든 바이러스의 번호는 K이하의 자연수로만 주어진다. N+2번째 줄에는 S, X, Y가 공백을 기준으로 구분되어 주어진다. (0 ≤ S ≤ 10,000, 1 ≤ X, Y  N)

 

 

 

출력

S초 뒤에 (X,Y)에 존재하는 바이러스의 종류를 출력한다. 만약 S초 뒤에 해당 위치에 바이러스가 존재하지 않는다면, 0을 출력한다.

 

 

예제

 

 

코드

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
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.StringTokenizer;
 
public class Main_BJ_18405_경제적전염 {
    
    static class info implements Comparable<info>{
        int x, y, index, time;
 
        public info(int x, int y, int index, int time) {
            this.x = x;
            this.y = y;
            this.index = index;
            this.time = time;
        }
 
        @Override
        public int compareTo(info o) {
            return index-o.index;
        }
    }
    
    static int N,K,S,X,Y;
    static int [][] arr;
    static int [] dx = {-1,0,1,0};
    static int [] dy = {0,1,0,-1};
    static ArrayList<info> list = new ArrayList<>();
 
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;
        
        st = new StringTokenizer(br.readLine()," ");
        
        N = Integer.parseInt(st.nextToken());
        K = Integer.parseInt(st.nextToken());
        
        arr = new int[N][N];
        
        for(int i=0;i<N;i++) {
            st = new StringTokenizer(br.readLine()," ");
            for(int j=0;j<N;j++) {
                arr[i][j]= Integer.parseInt(st.nextToken());
                if(arr[i][j]!=0) {
                    list.add(new info(i,j,arr[i][j],0));
                }
            }
        }
        
        Collections.sort(list);
        
        st = new StringTokenizer(br.readLine()," ");
        S = Integer.parseInt(st.nextToken());
        X = Integer.parseInt(st.nextToken());
        Y = Integer.parseInt(st.nextToken());
        
        bfs();
        
        System.out.println(arr[X-1][Y-1]);
 
    }
    
    public static void bfs() {
        while(!list.isEmpty()) {
            info temp = list.remove(0);
            int x = temp.x;
            int y = temp.y;
            int num = temp.index;
            int time = temp.time;
            if(time==S) break;
            for(int i=0;i<4;i++) {
                int nx = x +dx[i];
                int ny = y +dy[i];
                if(range(nx,ny) && arr[nx][ny]==0) {
                    arr[nx][ny]=num;
                    list.add(new info(nx,ny,num,time+1));
                }
            }
        }
        
    }
    
    public static boolean range(int x, int y) {
        return x>=0 && y>=0 && x<&& y<N;
    }
 
}
cs

 

 

풀이방법

시험관의 크기와 바이러스의 위치 정보가 주어졌을 때, S초가 지난 후에 (X, Y)에 존재하는 바이러스의 종류를 출력하는 문제였습니다.  번호가 낮은 종류의 바이러스부터 먼저 증식하기 때문에 바이러스 정보를 넣은 list를 먼저 정렬해주고 bfs를 이용해 상 하 좌 우로 확인하여 바이러스를 증식해나갔습니다. S초가 지난 후에는 반복문을 종료해 해당 (x, y)에 존재하는 바이러스의 종류를 출력해주었습니다.

 

'문제 > 백준' 카테고리의 다른 글

백준 1261번 알고번 알고스팟 [JAVA]  (0) 2021.03.24
백준 2636번 치즈 [JAVA]  (0) 2021.03.24
백준 1966번 프린터 큐 [JAVA]  (0) 2021.03.23
백준 7568번 덩치 [JAVA]  (0) 2021.03.23
백준 1717번 집합의 표현 [JAVA]  (0) 2021.03.22

문제

여러분도 알다시피 여러분의 프린터 기기는 여러분이 인쇄하고자 하는 문서를 인쇄 명령을 받은 ‘순서대로’, 즉 먼저 요청된 것을 먼저 인쇄한다. 여러 개의 문서가 쌓인다면 Queue 자료구조에 쌓여서 FIFO - First In First Out - 에 따라 인쇄가 되게 된다. 하지만 상근이는 새로운 프린터기 내부 소프트웨어를 개발하였는데, 이 프린터기는 다음과 같은 조건에 따라 인쇄를 하게 된다.

  1. 현재 Queue의 가장 앞에 있는 문서의 ‘중요도’를 확인한다.
  2. 나머지 문서들 중 현재 문서보다 중요도가 높은 문서가 하나라도 있다면, 이 문서를 인쇄하지 않고 Queue의 가장 뒤에 재배치한다. 그렇지 않다면 바로 인쇄를 한다.

예를 들어 Queue에 4개의 문서(A B C D)가 있고, 중요도가 2 1 4 3 라면 C를 인쇄하고, 다음으로 D를 인쇄하고 A, B를 인쇄하게 된다.

여러분이 할 일은, 현재 Queue에 있는 문서의 수와 중요도가 주어졌을 때, 어떤 한 문서가 몇 번째로 인쇄되는지 알아내는 것이다. 예를 들어 위의 예에서 C문서는 1번째로, A문서는 3번째로 인쇄되게 된다.

 

 

입력

첫 줄에 테스트케이스의 수가 주어진다. 각 테스트 케이스는 두 줄로 이루어져 있다.

테스트 케이스의 첫 번째 줄에는 문서의 개수 N(1 ≤ N ≤ 100)과, 몇 번째로 인쇄되었는지 궁금한 문서가 현재 Queue에서 몇 번째에 놓여 있는지를 나타내는 정수 M(0 ≤ M < N)이 주어진다. 이때 맨 왼쪽은 0번째라고 하자. 두 번째 줄에는 N개 문서의 중요도가 차례대로 주어진다. 중요도는 1 이상 9 이하의 정수이고, 중요도가 같은 문서가 여러 개 있을 수도 있다.

 

 

출력

각 테스트 케이스에 대해 문서가 몇 번째로 인쇄되는지 출력한다.

 

 

예제

 

코드

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
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.StringTokenizer;
 
public class Main_BJ_1966_프린터큐 {
    
    static class info{
        int index, importance;
 
        public info(int index, int importance) {
            this.index = index;
            this.importance = importance;
        }
        
    }
 
    public static void main(String[] args) throws NumberFormatException, IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;
        StringBuilder sb = new StringBuilder();
        
        Queue<info> queue = new LinkedList<>();
        PriorityQueue<info> pq = new PriorityQueue<>(new Comparator<info>() {
 
            @Override
            public int compare(info o1, info o2) {
                // TODO Auto-generated method stub
                return (o1.importance-o2.importance) * -1;
            }
        });
        
        int T = Integer.parseInt(br.readLine());
        
        for(int i=0;i<T;i++) {
            st = new StringTokenizer(br.readLine()," ");
            int N = Integer.parseInt(st.nextToken());
            int M = Integer.parseInt(st.nextToken());
            
            st = new StringTokenizer(br.readLine()," ");
            for(int j=0;j<N;j++) {
                int value = Integer.parseInt(st.nextToken());
                queue.offer(new info(j,value));
                pq.offer(new info(j,value));
            }
            
            int cnt=0;
            while(true) {
                
                if(queue.peek().importance==pq.peek().importance) {
                    if(queue.peek().index==M) break;
                    else {
                        cnt++;
                        queue.poll();
                        pq.poll();
                    }
                }
                else {
                    queue.offer(queue.poll());
                }
            }
            queue.clear(); pq.clear();
            sb.append((cnt+1)+"\n");
        }
        System.out.println(sb.toString());
 
    }
}
cs

 

 

풀이방법

중요도가 높은 순서대로 출력하는데 큐에서 M번째 놓여 있는 정수가 몇 번째로 인쇄되는지 알아내는 문제였습니다.

저는 인덱스와 중요도를 저장하는 큐와 중요도 높은 순으로 정렬한 우선순위 큐를 이용하여 구현하였습니다.

먼저, 인덱스와 중요도를 큐와 우선순위 큐에 각각 저장한 뒤, 중요도 높은 문서부터 출력하기 위해 while문을 통해 우선순위 맨 앞에 저장된 중요도와 큐에 저장된 중요도를 비교해서 같으면 문제에서 원하던 정수이므로 그동안 출력한 횟수+1을 하여 출력해주고 같지 않을 경우 값을 맨 뒤에 저장해 우선순위 큐 맨 앞에 저장된 중요도와 같은 중요도를 찾을 수  있도록 구현했습니다.

 

 

'문제 > 백준' 카테고리의 다른 글

백준 2636번 치즈 [JAVA]  (0) 2021.03.24
백준 18405번 경제적 전염 [JAVA]  (0) 2021.03.23
백준 7568번 덩치 [JAVA]  (0) 2021.03.23
백준 1717번 집합의 표현 [JAVA]  (0) 2021.03.22
백준 1976번 여행가자 [JAVA]  (0) 2021.03.22

문제

우리는 사람의 덩치를 키와 몸무게, 이 두 개의 값으로 표현하여 그 등수를 매겨보려고 한다. 어떤 사람의 몸무게가 x kg이고 키가 y cm라면 이 사람의 덩치는 (x, y)로 표시된다. 두 사람 A와 B의 덩치가 각각 (x, y), (p, q)라고 할 때 x > p 그리고 y > q이라면 우리는 A의 덩치가 B의 덩치보다 "더 크다"라고 말한다. 예를 들어 어떤 A, B 두 사람의 덩치가 각각 (56, 177), (45, 165)라고 한다면 A의 덩치가 B보다 큰 셈이 된다. 그런데 서로 다른 덩치끼리 크기를 정할 수 없는 경우도 있다. 예를 들어 두 사람 C와 D의 덩치가 각각 (45, 181), (55, 173)이라면 몸무게는 D가 C보다 더 무겁고, 키는 C가 더 크므로, "덩치"로만 볼 때 C와 D는 누구도 상대방보다 더 크다고 말할 수 없다.

N명의 집단에서 각 사람의 덩치 등수는 자신보다 더 "큰 덩치"의 사람의 수로 정해진다. 만일 자신보다 더 큰 덩치의 사람이 k명이라면 그 사람의 덩치 등수는 k+1이 된다. 이렇게 등수를 결정하면 같은 덩치 등수를 가진 사람은 여러 명도 가능하다. 아래는 5명으로 이루어진 집단에서 각 사람의 덩치와 그 등수가 표시된 표이다.

이름(몸무게, 키) 덩치 등수

A (55, 185) 2
B (58, 183) 2
C (88, 186) 1
D (60, 175) 2
E (46, 155) 5

위 표에서 C보다 더 큰 덩치의 사람이 없으므로 C는 1등이 된다. 그리고 A, B, D 각각의 덩치보다 큰 사람은 C 뿐이므로 이들은 모두 2등이 된다. 그리고 E보다 큰 덩치는 A, B, C, D 이렇게 4명이므로 E의 덩치는 5등이 된다. 위 경우에 3등과 4등은 존재하지 않는다. 여러분은 학생 N명의 몸무게와 키가 담긴 입력을 읽어서 각 사람의 덩치 등수를 계산하여 출력해야 한다.

 

 

입력

첫 줄에는 전체 사람의 수 N이 주어진다. 그리고 이어지는 N개의 줄에는 각 사람의 몸무게와 키를 나타내는 양의 정수 x와 y가 하나의 공백을 두고 각각 나타난다.

 

 

출력

여러분은 입력에 나열된 사람의 덩치 등수를 구해서 그 순서대로 첫 줄에 출력해야 한다. 단, 각 덩치 등수는 공백 문자로 분리되어야 한다.

 

 

예제

 

 

코드

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
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.StringTokenizer;
 
public class Main_BJ_7568_덩치 {
    static class info{
        int weight, height, cnt;
 
        public info(int weight, int height, int cnt) {
            this.weight = weight;
            this.height = height;
            this.cnt = cnt;
        }
    }
 
    public static void main(String[] args) throws NumberFormatException, IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;
        StringBuilder sb = new StringBuilder();
        
        int N = Integer.parseInt(br.readLine());
        
        ArrayList<info> list = new ArrayList<>();
        
        for(int i=0;i<N;i++) {
            st = new StringTokenizer(br.readLine()," ");
            list.add(new info(Integer.parseInt(st.nextToken()),Integer.parseInt(st.nextToken()),0));
        }
        
        int count=0;
        for(int i=0;i<N;i++) {
            count=0;
            int w = list.get(i).weight;
            int h = list.get(i).height;
            for(int j=0;j<N;j++) {
                if(w<list.get(j).weight && h<list.get(j).height) count++;
            }
            list.get(i).cnt=count;
        }
        
        for(int i=0;i<list.size();i++) {
            sb.append((list.get(i).cnt+1)+" ");
        }
        System.out.println(sb.toString());
 
    }
 
}
cs

 

 

풀이방법

학생 N명의 몸무게와 키가 담긴 입력을 통해 각 사람의 덩치 등수를 계산하는 문제였습니다.

저는 학생들의 키와 몸무게를 비교하기 위해서 list에 키, 몸무게, 나보다 덩치 큰 학생의 수를 저장할 수 있도록 하였습니다. 학생들의 정보를 다 저장하고 난 뒤, 첫 번째 학생부터 list에 들어있는 학생들과 비교해 자신보다 덩치가 큰 학생이 있는지 확인하여 자신보다 큰 학생들의 수를 cnt에 저장해주었습니다. 그리고 자신의 등수를 계산하는 문제이기 때문에 cnt에 +1을 더해줘 등수를 출력해주었습니다.

 

 

'문제 > 백준' 카테고리의 다른 글

백준 18405번 경제적 전염 [JAVA]  (0) 2021.03.23
백준 1966번 프린터 큐 [JAVA]  (0) 2021.03.23
백준 1717번 집합의 표현 [JAVA]  (0) 2021.03.22
백준 1976번 여행가자 [JAVA]  (0) 2021.03.22
백준 1991번 트리 순회 [JAVA]  (0) 2021.03.17

문제

초기에 {0}, {1}, {2}, ... {n} 이 각각 n+1개의 집합을 이루고 있다. 여기에 합집합 연산과, 두 원소가 같은 집합에 포함되어 있는지를 확인하는 연산을 수행하려고 한다.

집합을 표현하는 프로그램을 작성하시오.

 

 

입력

첫째 줄에 n(1 ≤ n ≤ 1,000,000), m(1 ≤ m ≤ 100,000)이 주어진다. m은 입력으로 주어지는 연산의 개수이다. 다음 m개의 줄에는 각각의 연산이 주어진다. 합집합은 0 a b의 형태로 입력이 주어진다. 이는 a가 포함되어 있는 집합과, b가 포함되어 있는 집합을 합친다는 의미이다. 두 원소가 같은 집합에 포함되어 있는지를 확인하는 연산은 1 a b의 형태로 입력이 주어진다. 이는 a와 b가 같은 집합에 포함되어 있는지를 확인하는 연산이다. a와 b는 n 이하의 자연수 또는 0이며 같을 수도 있다.

 

 

출력

1로 시작하는 입력에 대해서 한 줄에 하나씩 YES/NO로 결과를 출력한다. (yes/no 를 출력해도 된다)

 

 

예제

 

 

코드

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
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
 
public class Main_BJ_1717_집합의표현 {
    static int N,M;
    static int [] arr;
 
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringBuilder sb = new StringBuilder();
        StringTokenizer st;
        
        st = new StringTokenizer(br.readLine()," ");
        N = Integer.parseInt(st.nextToken());
        M = Integer.parseInt(st.nextToken());
        arr = new int [N+1];
        
        for(int i=0;i<arr.length;i++) arr[i]=i;
        
        for(int i=0;i<M;i++) {
            st = new StringTokenizer(br.readLine()," ");
            int o = Integer.parseInt(st.nextToken());
            int a = Integer.parseInt(st.nextToken());
            int b = Integer.parseInt(st.nextToken());
            
            if(o==0) {
                union(a,b);
            }else {
                if(find(a)==find(b)) sb.append("YES\n");
                else sb.append("NO\n");
            }
        }
        System.out.println(sb.toString());
        
    }
    
    public static int find(int x) {
        if(arr[x]==x) return x;
        return arr[x] = find(arr[x]);
    }
    
    public static void union(int a, int b) {
        int aRoot = find(a);
        int bRoot = find(b);
        
        if(aRoot != bRoot) arr[aRoot] = bRoot;
        
    }
 
}
cs

 

 

풀이방법

두 원소가 같은 집합에 포함되어 있는지를 확인하는 문제였습니다.

변수 o 가 0일 경우에는 두 집합을 합친다는 의미이므로 union()메소드를 통해 각 각의 루트를 찾아 두 원소가 다른 집합일 경우에는 집합의 루트를 같게 해 "두 원소가 같은 집합에 포함되어있다" 라고 표현해주었습니다.

변수 o가 1일 경우에는 두 원소가 같은 집합에 포함되어 있는지 확인하기 위해 find()메소드를 통해 루트가 같은지 확인하여 만약 같다면 yes를, 다르다면 no를 출력해주었습니다.

 

 

 

'문제 > 백준' 카테고리의 다른 글

백준 1966번 프린터 큐 [JAVA]  (0) 2021.03.23
백준 7568번 덩치 [JAVA]  (0) 2021.03.23
백준 1976번 여행가자 [JAVA]  (0) 2021.03.22
백준 1991번 트리 순회 [JAVA]  (0) 2021.03.17
백준 12865번 평범한 배낭 [JAVA]  (1) 2021.03.17

+ Recent posts