BOJ 2536

버스 갈아타기

문제출처

문제 해석

  • 버스의 노선이 주어졌을 때, 출발점에서 목표점까지 가기위해 타야하는 버스의 최소 수를 구하는 문제입니다.
  • 좌표 M,N에서 버스의 좌표(x1,y1,x2,y2)가 주어집니다.
  • M,N <= 100,000 k <= 5,000

설계(X)

  • 좌표범위가 매우 크기 때문에 2차원 배열을 쓰지못하도록 되어있습니다. 이를, 어떻게 구현할 지 생각을 하지못했습니다.
  • 공개코드처리된 ae04071님의 코드를 참조해 아이디어를 얻었습니다.
  • 버스의 노선이 좌표에 포함되는지 여부를 체크하여 bfs탐색을 하였습니다.
  • 먼저, 시작좌표가 포함되는 버스노선을 큐에 추가합니다.
  • 탐색을 진행하면서 현재 버스노선에서 갈 수 있는 노선을 찾는 식으로 구현합니다.

구현(X)

코드
#include <iostream>
#include <queue>
using namespace std;

struct info{
    int x1;
    int y1;
    int x2;
    int y2;
    bool is_in(const int& x, const int& y)const{
        return (x>=x1 && x <= x2 && y >= y1 && y <= y2);
    }
    bool is_in(const info& a)const{
        return (a.x1 <=x2 && a.x2 >= x1 && a.y1<=y2 && a.y2 >= y1);
    }

};
void swap(int &a, int &b){
    int tmp = a;
    a = b;
    b = tmp;
}
int visited[5001];
info bus[5001];
int M,N,K;
int sx,sy,dx,dy;
queue<int> q;
int bfs(){
    for (int i = 0; i <K ;i++){
        if (bus[i].is_in(sx,sy)) {
            q.push(i);
            visited[i] = 1;
        }
    }
    while (!q.empty()){
        int idx = q.front();
        if (bus[idx].is_in(dx,dy)){
            return visited[idx];
        }
        q.pop();
        for (int i = 0; i < K; i++){
            if (visited[i]) continue;
            if (bus[idx].is_in(bus[i])){
                visited[i] = visited[idx]+1;
                q.push(i);
            }
        }
    }
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin >> M >> N >> K;
    for (int i =0 ; i < K; i++){
        int num,x1,y1,x2,y2;
        cin >> num >> x1 >> y1 >> x2 >> y2;

        if (y1 > y2) swap(y1,y2);
        if (x1 > x2) swap(x1,x2);
        bus[i] = {x1,y1,x2,y2};
    }
    cin >> sx >> sy >> dx >> dy;
    cout << bfs()<<"\n";
    return 0;
}

디버깅
제출결과
  • 120ms

마무리

  • bfs탐색의 응용문제였습니다. 좌표를 X,Y좌표로 나누어 bfs탐색을 진행하는 방식으로 구현하려고 하였으나, 실패하였습니다. 각 버스노선 자체를 체크하게 되면 더욱 간단하게 구현할 수 있었습니다.
  • 문제를 고정적인 관념으로 바라보지 않게 시야를 조금 더 넓혀야 할 것 같습니다.