본문 바로가기
Algorithm/백준

[백준] Gold V. 맥주 마시면서 걸어가기

by 미네구스 2024. 6. 9.

 

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

 

 

사용 알고리즘
  • 그래프 탐색
  • BFS
풀이
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.Array;
import java.util.*;

public class Main {
    static int t, n;
    static StringBuilder sb = new StringBuilder();
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        t = Integer.parseInt(br.readLine());

        for(int k = 0; k < t; k++) {
            n = Integer.parseInt(br.readLine());

            List<int[]> location = new ArrayList<>();
            boolean [] visited = new boolean[n + 2];
            List<List<Integer>> graph = new ArrayList<>();

            for(int i = 0; i < n + 2; i++) {
                StringTokenizer st = new StringTokenizer(br.readLine());
                int x = Integer.parseInt(st.nextToken());
                int y = Integer.parseInt(st.nextToken());
                location.add(new int[]{x, y});
            }


            for(int i = 0; i < n + 2; i++){
                graph.add(new ArrayList<>());
            }

            for(int i = 0; i < n + 2; i++){
                for(int j = i + 1; j < n + 2; j++) {
                    if (possible(location.get(i), location.get(j))) {
                        graph.get(i).add(j);
                        graph.get(j).add(i);
                    }
                }
            }

            if (bfs(graph, visited)) sb.append("happy");
            else sb.append("sad");

            if (k < t - 1) {
                sb.append("\n");
            }
        }

        System.out.print(sb);
    }

    public static boolean bfs(List<List<Integer>> graph, boolean[] visited) {
        Queue<Integer> queue = new LinkedList<>();
        queue.add(0);
        visited[0] = true;
        while(!queue.isEmpty()) {
            int node = queue.poll();
            for(int next : graph.get(node)) {
                if (visited[next]) continue;

                if (next == n + 1) return true; // 간선의 개수가 n + 1개, 즉 끝점에 도달했다는 뜻
                visited[next] = true;
                queue.add(next);
            }
        }
        return false;
    }

    public static boolean possible(int [] x, int [] y) {
        if ((Math.abs(x[0] - y[0]) + Math.abs(x[1] - y[1])) <= 1000) return true;
        return false;
    }
}

 

회고

 

그래프에 익숙하지 않아서 까다로운 문제였다. 

 

일단, 해당 좌표를 그래프로 변환하는 과정에서 거리가 1000 아래일 때만 변환해주는 생각을 하지 못했다.

0 0
1000 0
1000 1000
2000 1000

 

이렇게 예제가 주어질 때,

0 -- 1 -- 2 -- 3

 

이런식으로 전부 이어진 형태가 된다.

 

반면에,

0 0
1000 0
2000 1000
2000 2000

 

0 -- 1

2 -- 3

 

1, 2 사이의 거리가 1000이 넘기 때문에 이렇게 나눠져서 그래프가 형성된다.

 

문제에서 (0, 0)과 같은 좌표를 List<int []> position에 한번에 묶어서 담아주고, 이중 포문을 돌면서 거리가 1000이 넘는지 체크한다.

for(int i = 0; i < n + 2; i++){
    for(int j = i + 1; j < n + 2; j++) {
        if (possible(location.get(i), location.get(j))) {
            graph.get(i).add(j);
            graph.get(j).add(i);
        }
    }
}

 

이중 for문을 왜 도는지에 대해서 좀 헷갈렸는데, 쉽게 이야기 해서 1 -- 2 뿐만 아닌 1 -- 3, 1 -- 4와 같은 모든 노드에 대해서 이어질 수 있는지 체크해서 그렇다. 

 

bfs가 true인 조건은, 

next == n + 1

 

인데, next (현재 보고 있는 노드)가 3이라면, 끝까지 도달했다는 뜻 이므로 true를 리턴해 준다.

 

2번째 예시같은 경우, next를 출력해보면 1이기 때문에 false를 리턴해준다.

 

 

로직을 봤을때 그렇게 어렵지 않은 문제인데, 많이 풀어봐야겠다. 

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

[백준] Silver 1. 봄버맨  (0) 2024.06.10
[백준] Silver II. 트리의 부모 찾기  (0) 2024.06.09
[백준] Silver II. 촌수 계산  (0) 2024.06.09
[백준] Silver II. 연결 요소의 개수  (0) 2024.06.06
[백준] Level IV. 빙산  (0) 2024.06.03