# 유형 : 그래프 , BFS, DFS ,플로이드와샬

# 두 가지 방법으로 풀었다. 첫 번째는  플로이드 와샬 방법, 그리고 두 번째 방법은 평소 많이 사용하던 BFS로 풀었다. 

플로이드 와샬 방법으로는 집(출발지) 편의점(거쳐가는 정점) 락 페스티벌(도착점)으로 잡고 알고리즘을 사용하면 된다.

BFS는 인접 리스틀 사용하여 BFS 알고리즘을 완성하면 된다. 꼭 한 방법으로만 푸는게 아니고 여러 방법으로 푸는 것도 알고리즘 실력에도 향상이 되니 여러 방법을 접하고 도전해보는 것을 추천한다.

 

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
package bj;
 
import java.awt.Point;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;
 
public class p9205_floyd {
    static int N;    
    static int arr[][];
    static ArrayList<Point> arrList;
    public static void main(String[] args) throws NumberFormatException, IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int testCases = Integer.parseInt(br.readLine());
        for(int tc=0; tc<testCases; tc++) {
            N = Integer.parseInt(br.readLine());
            
            arrList = new ArrayList<>();
            arr = new int[N+2][N+2];
            for(int i=0; i<N+2; i++)
                for(int j=0; j<N+2; j++)
                    arr[i][j]=999999;
            
            StringTokenizer st;
            
            for(int i=0; i<N+2; i++) {
                st = new StringTokenizer(br.readLine());
                int x = Integer.parseInt(st.nextToken());
                int y = Integer.parseInt(st.nextToken());
                
                arrList.add(new Point(x,y));
            }
            
            for(int i=0; i<N+2; i++) {
                for(int j=0; j<N+2; j++) {
                    if(i==j)
                        continue;
                    
                    Point current = arrList.get(i);
                    Point next = arrList.get(j);
                    
                    int dist = Math.abs(current.x-next.x)+Math.abs(current.y-next.y);
                    if(dist<=1000)
                        arr[i][j] = 1;
                }
            }
            floyd_warshall();
            if(0<arr[0][N+1&& arr[0][N+1]<999999)
                System.out.println("happy");
            else
                System.out.println("sad");
        }
    }
    public static void floyd_warshall() {
        for(int k=0; k<N+2; k++) {
            for(int i=0; i<N+2; i++) {
                for(int j=0; j<N+2; j++) {
                    if(arr[i][j] > arr[i][k] + arr[k][j])
                        arr[i][j] = arr[i][k] + arr[k][j];
                }
            }
        }
    }
    
}
 
cs

2) BFS를 이용한 풀이

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
package bj;
 
import java.awt.Point;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;
 
public class p9205 {
    static int N;    
//    static int arr[][];
    static Point arr[];
    static boolean visit[];
    static ArrayList<Integer> arrList[];
    public static void main(String[] args) throws NumberFormatException, IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int testCases = Integer.parseInt(br.readLine());
        for(int tc=0; tc<testCases; tc++) {
            N = Integer.parseInt(br.readLine());
            
            arrList = new ArrayList[N+2];
            visit = new boolean[N+2];
            for(int i=0; i<N+2; i++)
                arrList[i] = new ArrayList<>();
            
            arr = new Point[N+2];
            
            StringTokenizer st;
            
            for(int i=0; i<N+2; i++) {
                st = new StringTokenizer(br.readLine());
                int x = Integer.parseInt(st.nextToken());
                int y = Integer.parseInt(st.nextToken());
                
                arr[i] = new Point(x,y);
            }
            
            for(int i=0; i<N+1; i++) {
                for(int j=i+1; j<N+2; j++) {
                    float dist = (float) ((Math.abs(arr[i].x - arr[j].x) + Math.abs(arr[i].y -arr[j].y))/50.0);
                    if(dist <= 20) {
                        arrList[i].add(j);
                        arrList[j].add(i);
                    }
                }
            }
            
            if(bfs())
                System.out.println("happy");
            else
                System.out.println("sad");
            
        }
    }
    private static boolean bfs() {
        // TODO Auto-generated method stub
        Queue<Integer> queue = new LinkedList<>();
        queue.add(0);
        visit[0= true;
        
        while(!queue.isEmpty()) {
            int index =queue.poll();
//            System.out.println(index);
            if(index == N+1)
                return true;
            
            for(int i=0; i<arrList[index].size(); i++) {
//                System.out.println(arrList[index].get(i));
                if(!visit[arrList[index].get(i)]) {
                    visit[arrList[index].get(i)] = true;
                    queue.add(arrList[index].get(i));
                }
            }
        }
        return false;
    }
}
 
cs

# 유형 : 시뮬레이션

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
package bj;
 
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
 
public class p1592 {
    static int N,M,L;
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
        M = Integer.parseInt(st.nextToken());
        L = Integer.parseInt(st.nextToken());
    
        int arr[] = new int[N];
        int cnt=0;
        int index=0;
        while(true) {
            arr[index]++;
            if(arr[index] == M)
                break;
            
            if(arr[index]%2 == 0) {
                if(index + L >= N) {
                    index = L-N+index;
                }else {
                    index+=L;
                }
            }else if(arr[index]%2 ==1){
                if(index-L<0) {
                    index = N-L+index;
                }else
                    index-=L;
            }
            cnt++;
        }
        System.out.println(cnt);
    }
}
 
cs

# 유형 : 탐색, 플로이드 와샬

# dfs,bfs 로도 풀 수 있지만 문제를 보면 시작점, 도착점, 중간점을 이용해서 문제를 해결할 수 있다. 예를 들어 1번 사건이 2번 사건보다 먼저 일어났고, 2번 사건이 3번 사건 보다 먼저 일어났다면 1번과 3번중에 먼저 일어난 사건은 1번이다. 플로이드 와샬로 해결해보자면 1번이 시작점, 2번이 중간점, 3번이 도착점이다.

예를 들어 1은 뒤에가 먼저 일어난 사건일 경우, -1은 앞에가 먼저 일어난 사건일 경우, 0은 모르는 경우이다. 따라서 맨 처음에는 모르는 경우로 초기화를 해주고  if(arr[i][j] == 0) {(arr[i][k] == 1 && arr[k][j] == 1 )} ======> arr[i][j] = 1

이런식으로 -1, 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
package bj;
 
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
 
public class p1613 {
    static int N,K,S;
    static int arr[][];
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
        K = Integer.parseInt(st.nextToken());
        
        arr = new int[N+1][N+1];
        for(int i=0; i<K; i++) {
            st = new StringTokenizer(br.readLine());
            int u = Integer.parseInt(st.nextToken());
            int v = Integer.parseInt(st.nextToken());
            arr[u][v] = -1;
            arr[v][u] = 1;
        }
        
        floyd_warshall();
        
        S = Integer.parseInt(br.readLine());
        for(int s=0; s<S; s++) {
            st = new StringTokenizer(br.readLine());
            int u = Integer.parseInt(st.nextToken());
            int v = Integer.parseInt(st.nextToken());
            System.out.println(arr[u][v]);
        }
        
    }
    
    public static void floyd_warshall() {
        for(int k=1; k<=N; k++) {
            for(int i=1; i<=N; i++) {
                for(int j=1; j<=N; j++) {
                    if(arr[i][j] == 0) {
                        if(arr[i][k] == 1 && arr[k][j] == 1)
                            arr[i][j] = 1;
                        else if(arr[i][k] == -1 && arr[k][j] == -1)
                            arr[i][j] = -1;
                    }
                }
            }
        }
    }
}
 
cs

# 유형 : 그래프, BFS

# 보통 풀던 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
package bj;
 
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 p6593 {
    static int moveY[] = {-1,0,1,0,0,0};
    static int moveX[] = {0,1,0,-1,0,0};
    static int moveZ[] = {0,0,0,0,1,-1};
    static int L,R,C;
    static char arr[][][];
    static int map[][][];
    static boolean visit[][][],check=false;
    static Po start, end;
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        while(true) {
            check = false;
            StringTokenizer st = new StringTokenizer(br.readLine());
            if(!st.hasMoreTokens())
                st = new StringTokenizer(br.readLine());
            
            L = Integer.parseInt(st.nextToken());
            R = Integer.parseInt(st.nextToken());
            C = Integer.parseInt(st.nextToken());
            if(L==0 && R==0 && C==0) {
                break;
            }
            arr = new char[L][R][C];
            map = new int[L][R][C];
            visit = new boolean[L][R][C];
            
            for(int l=0; l<L; l++) {
                for(int r=0; r<R; r++) {
                    String str = br.readLine();
                    
                    if(str.equals("")) 
                        str = br.readLine();
                        
                    for(int c=0; c<C; c++) {
                        char ch = str.charAt(c);
                        if(ch == 'S') {
                            start = new Po(c,r,l);
                        }else if(ch == 'E') {
                            end = new Po(c,r,l);
                        }
                        arr[l][r][c] = ch;
                    }
                }
            }
            
            bfs(start);
            if(!check) {
                System.out.println("Trapped!");
            }
        }
        
        
    }
    public static void bfs(Po p) {
        Queue<Po> queue = new LinkedList<>();
        queue.add(p);
        visit[p.z][p.y][p.x] = true;
        
        while(!queue.isEmpty()) {
            Po tmp = queue.poll();
            if(tmp.x == end.x && tmp.y == end.y && tmp.z == end.z) {
                
                System.out.println("Escaped in "+map[tmp.z][tmp.y][tmp.x]+" minute(s).");
                check = true;
                return;
            }
            
            for(int d=0; d<6; d++) {
                int newX = tmp.x + moveX[d];
                int newY = tmp.y + moveY[d];
                int newZ = tmp.z + moveZ[d];
                
                if(0<=newX && newX<&& 0<=newY && newY<&& 0<=newZ && newZ<&& !visit[newZ][newY][newX]) {
                    if(arr[newZ][newY][newX]!='#') {
                        visit[newZ][newY][newX] = true;
                        map[newZ][newY][newX] = map[tmp.z][tmp.y][tmp.x] + 1;
                        queue.add(new Po(newX,newY,newZ));
                    }
                }
            }
        }
        
    }
    public static class Po{
        int x;
        int y;
        int z;
        public Po(int x,int y,int z) {
            this.x=x;
            this.y=y;
            this.z=z;
        }
    }
}
 
cs

# 유형 : 그래프 탐색, 최단경로, 플로이드 와샬

# 문제를 잘 보면 그래프에서 모든 정점 사이의 최단 경로를 구하는 문제라는 것을 알 수 있다. 이 때 떠오르는 알고리즘은 플로이드 와샬 알고리즘이다. 플로이드 와샬은 거쳐가는 정점을 기준으로 알고리즘을 수행하는 특징을 가지고 있고, 다이나믹 프로그래밍 기반이다. BFS로도 풀 수 있을 것 같지만 우선 플로이드 와샬로 문제를 해결해보았다. 시간복잡도는 O(V^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
package bj;
 
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
 
public class p1389 {
    static int N,M;
    static int arr[][];
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
        M = Integer.parseInt(st.nextToken());
        arr = new int[N][N];
        for(int i=0; i<N; i++)
            for(int j=0; j<N; j++)
                arr[i][j] = 999999;
        
        for(int i=0; i<M; i++) {
            st = new StringTokenizer(br.readLine());
            int u = Integer.parseInt(st.nextToken());
            int v = Integer.parseInt(st.nextToken());
            arr[u-1][v-1= 1;
            arr[v-1][u-1= 1;
        }
        floyd_warshall();
        
        int min = 999999;
        int index = 0;
        for(int i=0; i<N; i++) {
            int sum = 0;
            for(int j=0; j<N; j++) {
                sum += arr[i][j];
            }
            if(min > sum) {
                min = sum;
                index = i;
            }
//            System.out.println(sum);
        }
        System.out.println(index+1);
    }
    
    public static void floyd_warshall() {
        for(int k=0; k<N; k++) {
            for(int i=0; i<N; i++) {
                for(int j=0; j<N; j++) {
                    arr[i][j] = Math.min(arr[i][j], arr[i][k]+arr[k][j]);
                }
            }
        }
    }
}
 
cs

# 유형 : 그래프탐색, DFS

# 숫자가 부분 수열을 이룬다. 이 문제를 다르게 생각하면 숫자들이 사이클을 이룬다면 부분 수열이 된다. 따라서 DFS로 사이클을 체크해주면 된다.

 

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
package bj;
 
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
 
public class p2668 {
    static int N;
    static int arr[];
    static int result=0;
    static boolean visit[],cycle[];
    public static void main(String[] args) throws NumberFormatException, IOException {
    
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        N = Integer.parseInt(br.readLine());
        
        arr = new int[N+1];
        visit = new boolean[N+1];
        cycle = new boolean[N+1];
        
        for(int i=1; i<=N; i++) {
            arr[i] = Integer.parseInt(br.readLine());
        }
        
        for(int i=1; i<=N; i++) {
            for(int j=1; j<=N; j++)
                visit[j] = cycle[j];
            dfs(i,arr[i]);
        }
        System.out.println(result);
        for(int i=1; i<=N; i++) {
            if(cycle[i])
                System.out.println(i);
        }
    }
    
    public static boolean dfs(int start_val, int arr_val) {
//        System.out.println(start_val + " "+arr_val);
        if(visit[arr_val] == true)
            return false;
        
        visit[arr_val] = true;
        
        if(start_val == arr_val || dfs(start_val, arr[arr_val])) {
            result++;
//            System.out.println(start_val+" "+"cehck"+ arr_val);
            cycle[arr_val] = true;
            return true;
        }
        return false;
    }
}
 
cs

# 유형 : 그래프, 탐색, BFS

# 간단한 BFS 문제. 큐에 넣을 때마다 촌수를 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
 
import java.awt.Point;
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 p2644 {
    static boolean check = false;
    static int N,M;
    static int start,end;
    static int arr[][];
    static boolean visit[];
    public static void main(String[] args) throws NumberFormatException, IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        N = Integer.parseInt(br.readLine());
        StringTokenizer st = new StringTokenizer(br.readLine());
        start = Integer.parseInt(st.nextToken());
        end = Integer.parseInt(st.nextToken());
        M = Integer.parseInt(br.readLine());
        
        arr = new int[N+1][N+1];
        visit = new boolean[N+1];
        for(int i=0; i<M; i++) {
            st = new StringTokenizer(br.readLine());
            int u = Integer.parseInt(st.nextToken());
            int v = Integer.parseInt(st.nextToken());
            arr[u][v] = 1;
            arr[v][u] = 1;
        }
        
        bfs(start);
        if(!check) {
            System.out.println(-1);
        }
    }
    
    public static void bfs(int begin) {
        Queue<Point> queue = new LinkedList<Point>();
        visit[begin] = true;
        queue.add(new Point(begin, 0));
        
        while(!queue.isEmpty()) {
            Point po = queue.poll();
            
            if(po.x == end) {
                System.out.println(po.y);
                check = true;
                return;
            }
            
            for(int i=1; i<=N; i++) {
                if(arr[po.x][i]==1 && !visit[i]) {
                    visit[i] = true;
                    queue.add(new Point(i, po.y+1));
                }
            }
        }
    }
}
 
cs

# 유형 : 탐색, 그래프

# 방법은 여러가지 있을텐데, 그냥 귀찮아서 입력받을때 적록색약인 사람을 위한 배열을 하나 더 만들었다.

그다음 BFS를 2번 돌리면 문제를 해결할 수 있다.

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
package bj;
 
import java.awt.Point;
import java.io.*;
import java.util.LinkedList;
import java.util.Queue;
 
public class p10026 {
    static int N;
    static char arr[][], map[][];
    static boolean visit[][];
    static int moveX[] = {0,1,0,-1};
    static int moveY[] = {-1,0,1,0};
    static int cnt1,cnt2=0;
    public static void main(String[] args) throws NumberFormatException, IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        N = Integer.parseInt(br.readLine());
        
        arr = new char[N][N];
        map = new char[N][N];
        visit = new boolean[N][N];
        
        for(int i=0; i<N; i++) {
            String str = br.readLine();
            for(int j=0; j<N; j++) {
                char ch = str.charAt(j);
                if(ch=='G') {
                    arr[i][j] = ch;
                    map[i][j] = 'R';
                }else {
                    arr[i][j] = ch;
                    map[i][j] = ch;
                }
            }
        }
        
        for(int i=0; i<N; i++) {
            for(int j=0; j<N; j++) {
                if(!visit[i][j]) {
                    bfs(i,j,arr);
                    cnt1++;
                }
            }
        }
        visit = new boolean[N][N];
        for(int i=0; i<N; i++) {
            for(int j=0; j<N; j++) {
                if(!visit[i][j]) {
                    bfs(i,j,map);
                    cnt2++;
                }
            }
        }
        System.out.println(cnt1+" "+cnt2);
    }
    
    public static void bfs(int i, int j, char ar[][]) {
        Queue<Point> queue = new LinkedList<Point>();
        char ch = ar[i][j];
        queue.add(new Point(j,i));
        visit[i][j] = true;
        while(!queue.isEmpty()) {
            Point p = queue.poll();
            int x = p.x;
            int y = p.y;
            
            for(int d=0; d<4; d++) {
                int newX = x + moveX[d];
                int newY = y + moveY[d];
                
                if(0<=newX && newX<&& 0<=newY && newY<&& !visit[newY][newX]) {
                    if(!visit[newY][newX] && ar[newY][newX]==ch) {
                        visit[newY][newX] = true;
                        queue.add(new Point(newX, newY));
                    }
                }
            }
        }
    }
}
 
cs

+ Recent posts