코테/백준

[백준/JAVA] 9205번: 맥주 마시면서 걸어가기

imname1am 2024. 7. 14. 23:55
반응형

📖 문제

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

 

 

 

💡  풀이 방식

• 플로이드 와샬

필요 자료구조
- 위치들 저장용 리스트
- 위치들 중 두 지점 간 방문 가능한지 표시하는 2차원형 boolean형 배열

 

1. 모든 위치들을 입력받아 리스트에 저장한다.

2. 모든 위치들 중 2개를 골라 두 위치 간의 맨해튼 거리를 계산한다. (맨해튼 거리가 1000 이하라면 해당 거리로 이동할 수 있다.)

3. 지점 A에서 B로 이동 가능하고, B에서 C로 이동 가능하다면 A에서 C로 이동 가능하므로 이동 가능하다는 표시를 한다. (플로이드-와샬)

 

 

💥 유의사항

플로이드-와샬은 시간 복잡도가 O(N^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
import java.util.*;
import java.io.*;
 
public class Main {
    static int T;
    static StringBuilder sb = new StringBuilder();
    
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;
        
        T = Integer.parseInt(br.readLine());
        while(T --> 0) {
            int N = Integer.parseInt(br.readLine());
            
            // 리스트에 위치들 저장
            List<int[]> list = new ArrayList<>();
            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());
                
                list.add(new int[]{x,y});
            }
            
            boolean[][] flag = new boolean[N+2][N+2];   // 도착 가능한지 나타내는 배열
            for(int i = 0 ; i < N+2 ; i++) {
                for(int j = 0 ; j < N+2 ; j++) {
                    int[] now = list.get(i);
                    int[] next = list.get(j);
                    
                    int dist = Math.abs(now[0- next[0]) + Math.abs(now[1- next[1]); // 맨해튼 거리 계산
                    if(dist <= 1000)
                        flag[i][j] = true;
                }
            }
            
            // [플로이드 와샬] A에서 B로 이동 가능하고, B에서 C로 이동 가능하면, A에서 C로 이동 가능
            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(flag[i][k] && flag[k][j])
                            flag[i][j] = true;
                    }
                }
            }
            
            sb.append(flag[0][N+1] ? "happy\n" : "sad\n");
        }
        
        System.out.println(sb.toString());
    }
}
cs

 

 

 

➕ 다른 풀이 방식

- BFS를 활용한 풀이1

1. 편의점 위치들 N개를 리스트에 저장한다. (상근이네 집, 펜타포트 락 페스티벌 좌표는 따로 변수에 저장해둔다.)

2. 상근이네 집 위치부터 큐에 추가하며 BFS를 수행한다.

  ㄴ 현재 위치와 락페스티벌 위치 간 맨해튼 거리가 1000 미터 이하면 방문 가능하다.

  ㄴ 현재 위치부터 방문하지 않은 다른 편의점들 위치들을 돌면서 두 위치 간 맨해튼 거리가 1000 이하면, 해당 지점을 방문 처리하고 큐에 추가해 마저 탐색한다.

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.util.*;
import java.io.*;
 
public class Main {
    static int T, N, sx, sy, dx, dy;
    static StringBuilder sb = new StringBuilder();
    
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;
        
        T = Integer.parseInt(br.readLine());
        while(T --> 0) {
            N = Integer.parseInt(br.readLine());
            
            List<int[]> list = new ArrayList<>();
            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());
                
                if(i == 0) {
                    sx = x;
                    sy = y;
                }
                else if(i == N+1) {
                    dx = x;
                    dy = y;
                }
                else {
                    list.add(new int[]{x,y});
                }
            }
            
            sb.append(bfs(list) ? "happy\n" : "sad\n");
        }
        System.out.println(sb.toString());
    }
    
    private static boolean bfs(List<int[] > list) {
        boolean[] visited = new boolean[N];
        
        Queue<int[]> q = new ArrayDeque<>();
        q.add(new int[] {sx, sy});
        
        while(!q.isEmpty()) {
            int[] now = q.poll();
            
            int px = now[0];
            int py = now[1];
            if(Math.abs(px-dx) + Math.abs(py-dy) <= 1000) {
                return true;
            }
            
            for(int i = 0 ; i < N ; i++) {
                if(!visited[i]) {
                    int nx = list.get(i)[0];
                    int ny = list.get(i)[1];
                    int dist = Math.abs(px-nx) + Math.abs(py-ny);
                    if(dist <= 1000) {
                        visited[i] = true;
                        q.add(new int[] {nx, ny});
                    }
                }
            }
        }
 
        return false;
    }
}
cs

 

 

 

 

- BFS 풀이2인데 약간 다르다

 

[BOJ] 백준 9205번 : 맥주 마시면서 걸어가기 (JAVA)

문제 송도에 사는 상근이와 친구들은 송도에서 열리는 펜타포트 락 페스티벌에 가려고 한다. 올해는 맥주를 마시면서 걸어가기로 했다. 출발은 상근이네 집에서 하고, 맥주 한 박스를 들고 출발

steady-coding.tistory.com

 


💦 어려웠던 점

- 맥주 한 박스에 20개 있고, 50미터에 한 병씩 맥주를 마신다는 조건을 어떻게 내가 충족시켜주어야 하나라는 문제..

- 가장 가까운 위치부터 정렬해서 방문하면서 해야 하나? 라는 생각을 했었다..

 

 

🧐 새로 알게 된 내용

- A에서 B로 갈 수 있으면, B에서 C도 갈 수 있게 하는 BFS

- 맨해튼 거리가 1000m 이내여야 하는 이유 : 맥주 1병 50m * (시작 지점-편의점) or (편의점-편의점) or (편의점-도착지) 간 20병 = 1000m

 

1회독 2회독 3회독 4회독 5회독
V        

(참고)

 

[BOJ] 백준 9205번 맥주 마시면서 걸어가기 (Java)

#9205 맥주 마시면서 걸어가기 난이도 : 실버 1 유형 : 그래프 / BFS / Floyd-Warshall 9205번: 맥주 마시면서 걸어가기 송도에 사는 상근이와 친구들은 송도에서 열리는 펜타포트 락 페스티벌에 가려고 한

loosie.tistory.com

 

반응형