본문 바로가기

알고리즘 문제풀이

[백준 9205] 맥주 마시면서 걸어가기 - c++

문제링크: https://www.acmicpc.net/problem/9205

 

9205번: 맥주 마시면서 걸어가기

문제 송도에 사는 상근이와 친구들은 송도에서 열리는 펜타포트 락 페스티벌에 가려고 한다. 올해는 맥주를 마시면서 걸어가기로 했다. 출발은 상근이네 집에서 하고, 맥주 한 박스를 들고 출발한다. 맥주 한 박스에는 맥주가 20개 들어있다. 목이 마르면 안되기 때문에 50미터에 한 병씩 마시려고 한다. 상근이의 집에서 페스티벌이 열리는 곳은 매우 먼 거리이다. 따라서, 맥주를 더 구매해야 할 수도 있다. 미리 인터넷으로 조사를 해보니 다행히도 맥주를 파는 편의

www.acmicpc.net


문제설명

송도에 사는 상근이와 친구들은 송도에서 열리는 펜타포트 락 페스티벌에 가려고 한다. 올해는 맥주를 마시면서 걸어가기로 했다. 출발은 상근이네 집에서 하고, 맥주 한 박스를 들고 출발한다. 맥주 한 박스에는 맥주가 20개 들어있다. 목이 마르면 안되기 때문에 50미터에 한 병씩 마시려고 한다.

상근이의 집에서 페스티벌이 열리는 곳은 매우 먼 거리이다. 따라서, 맥주를 더 구매해야 할 수도 있다. 미리 인터넷으로 조사를 해보니 다행히도 맥주를 파는 편의점이 있다. 편의점에 들렸을 때, 빈 병은 버리고 새 맥주 병을 살 수 있다. 하지만, 박스에 들어있는 맥주는 20병을 넘을 수 없다.

편의점, 상근이네 집, 펜타포트 락 페스티벌의 좌표가 주어진다. 상근이와 친구들이 행복하게 페스티벌에 도착할 수 있는지 구하는 프로그램을 작성하시오.

 

문제조건

첫째 줄에 테스트 케이스의 개수 t가 주어진다. (t ≤ 50)

각 테스트 케이스의 첫째 줄에는 맥주를 파는 편의점의 개수 n이 주어진다. (0 ≤ n ≤ 100).

다음 n+2개 줄에는 상근이네 집, 편의점, 펜타포트 락 페스티벌 좌표가 주어진다. 각 좌표는 두 정수 x와 y로 이루어져 있다. (두 값 모두 미터, -32768 ≤ x, y ≤ 32767)

송도는 직사각형 모양으로 생긴 도시이다. 두 좌표 사이의 거리는 x 좌표의 차이 + y 좌표의 차이 이다. (맨해튼 거리)

 

문제접근 - 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
82
83
84
85
86
87
88
#include <iostream>
#include <vector>
#include <cstring>
#include <queue>
using namespace std;
 
// 좌표 포인트 구조체
typedef struct point{
    int x;
    int y;
}pnt;
 
bool visited[102];   // 탐색할때 방문여부를 확인하기 위한 배열
 
 
vector<pnt> arr;     // 입력값을 받을 포인트 배열 벡터
 
 
// 맨해튼 거리를 계산하기 위한 함수
int getDistance(pnt p1, pnt p2){
    return abs(p1.x - p2.x) + abs(p1.y - p2.y);
}
 
// 맥주가 떨어지기 전에 도착지에 도착할 수 있는지 탐색하는 bfs 함수
void bfs(){
    // 방문표시 초기화
    memset(visited,false,sizeof(visited));
    queue<pnt> Q;    // 작업 큐 선언
    Q.push(arr[0]);  // 출발지 좌표 작업큐에 삽입
    visited[0= true;  // 출발지 방문 표시
    
    // 넓이 우선 탐색 시작
    while(!Q.empty()){
        pnt now = Q.front();  // 현재 좌표를 작업큐에서 꺼냄
 
        Q.pop();             // pop
        
        // 입력 배열 전체 탐색
        for(int i=0; i<arr.size(); i++){
            
            // 좌표 i가 현재좌표 now와 맨해튼 거리가 1000이하면서 방문하지 않았을 때
            if(getDistance(now, arr[i]) < 1001 and !visited[i]){
                
                // 좌표 i가 도착좌표면 happy 출력하고 함수 종료
                if(i==arr.size()-1){
                    cout << "happy" << endl;
                    return;
                }
                
                // 도착지가 아니면 방문표시를 한 후 작업큐에 좌표 입력
                visited[i] = true;
                Q.push(arr[i]);
            }
        }
    }
    // happy에 도달하지 못했으면 sad를 출력하고 함수 종료
    cout << "sad" <<endl;
}
 
int main(){
    int n;
    int T;
    
    cin >> T;
    
    // 좌표를 입력받을 pnt 구조체 변수
    pnt p;
    
    // 테스트 케이스 만큼 반복
    for(int tc = 0; tc<T; tc++){
        // 입력 배열 초기화
        arr.clear();
        cin >> n;
        cin >> p.x >> p.y;
        
        // 좌표 입력 받음
        for(int i=0; i<n+2; i++){
            cin >> p.x >> p.y;
            arr.push_back(p);
        }
        
        // 탐색 시작
        bfs();
    }
    return 0;
}
 
 
cs