어흥

[백준 19238] 스타트 택시 (C++) 본문

알고리즘/백준

[백준 19238] 스타트 택시 (C++)

라이언납시오 2021. 2. 23. 10:03
728x90
반응형

문제 링크: www.acmicpc.net/problem/19238

 

19238번: 스타트 택시

첫 줄에 N, M, 그리고 초기 연료의 양이 주어진다. (2 ≤ N ≤ 20, 1 ≤ M ≤ N2, 1 ≤ 초기 연료 ≤ 500,000) 연료는 무한히 많이 담을 수 있기 때문에, 초기 연료의 양을 넘어서 충전될 수도 있다. 다

www.acmicpc.net

1. 주의할 점

- 변수들을 헷갈리지 않도록 한다

- 초기화를 잘 처리해준다

- 특정 조건에 맞는 우선순위 큐를 사용하여 다음으로 태울 손님을 구한다

 

2. 구현

- 길에 대한 정보를 Arr[][] 함수에 저장한다

- 손님의 시작위치, 도착지점 위치를 P[][4] 배열에 담는다

- Need_fuel[] 배열에 대한 초기화를 수행한다. 해당 배열은 손님의 탑승위치 -> 도착위치까지의 최단 거리를 미리 구하여 값을 저장하는 배열이다

- People[][] 배열에 손님이 위치해 있을 경우, 몇 번 손님이 위치해 있는지 표시한다

- Cal() 함수를 통해 미리 Need_fuel[] 배열에 값을 저장한다

- mvToPeople 함수를 손님의 수 만큼 수행하며, 최단 거리에 위치한 손님들을 우선순위 큐에 넣은 후, 가장 조건에 부합하는 사람번호에 대한 처리를 수행한다. 이후, 부합하는 손님이 있는 경우에는 손님의 번호를, 없는 경우에는 -1을 반환한다. 이 때, 택시의 위치 변경, 남은 연료 수정한다

 

#define MAX 987654321
#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
struct info{
    int x,y,val,idx;
};
struct cmp{
    bool operator()(info &a, info &b){
        if(a.val==b.val){
            if(a.y==b.y)
                return a.x> b.x;
            return a.y > b.y;
        }
        return a.val > b.val;
    }
};
info tmp;
int arr[21][21];
int people[21][21];     //해당 위치에 있는 사람 표시
int num,mv,fuel;
int dx[4]={0,1,0,-1};
int dy[4]={-1,0,1,0};
int tx,ty,result;
bool finish[401]={false,};
int p[401][4];       //sy,sx,ey,ex
int need_fuel[401];      //손님의 위치->도착지점까지 필요한 연료
bool check[21][21]={false,};

void cal(){     //손님의 위치->도착지점까지 필요한 연료 계산 함수
    for(int i=1;i<=mv;i++){
        for(int j=1;j<21;j++)
            for(int k=1;k<21;k++)
                check[j][k]=false;
        queue<info> q;
        tmp.x = p[i][1];
        tmp.y = p[i][0];
        tmp.val = 0;
        check[tmp.y][tmp.x] = true;
        q.push(tmp);
        while(!q.empty()){
            int cx = q.front().x;
            int cy = q.front().y;
            int cv = q.front().val;
            q.pop();
            if(cx==p[i][3] && cy == p[i][2]){
                need_fuel[i] = cv;
                break;
            }
            for(int j=0;j<4;j++){
                int nx = cx + dx[j];
                int ny = cy + dy[j];
                if(nx>0 && ny>0 && nx<=num && ny<=num && arr[ny][nx]==0 && !check[ny][nx]){
                    check[ny][nx]=true;
                    tmp.x = nx;
                    tmp.y = ny;
                    tmp.val = cv+1;
                    q.push(tmp);
                }
            }
        }
    }
}

int mvToPeople(){
    for(int j=1;j<21;j++)
        for(int k=1;k<21;k++)
            check[j][k]=false;
    queue<info> q;
    tmp.x = tx;
    tmp.y = ty;
    tmp.val = 0;
    q.push(tmp);
    check[ty][tx]=true;
    int mini=MAX;
    int arrived = -1;
    priority_queue<info,vector<info>,cmp> pq;

    while(!q.empty()){
        int cx = q.front().x;
        int cy = q.front().y;
        int cv = q.front().val;
        q.pop();
        if(people[cy][cx] && !finish[people[cy][cx]]){
            tmp.x = cx;
            tmp.y = cy;
            tmp.val = cv;
            tmp.idx = people[cy][cx];
            pq.push(tmp);
            mini = cv;
        }
        if(cv>=mini) continue;
        for(int i=0;i<4;i++){
            int nx = cx + dx[i];
            int ny = cy + dy[i];
            if(nx>0 && ny>0 && nx<=num && ny<=num && !check[ny][nx] && arr[ny][nx]==0 && cv<=fuel){
                check[ny][nx]=true;
                tmp.x = nx;
                tmp.y = ny;
                tmp.val = cv+1;
                q.push(tmp);
            }
        }
    }
    while(!pq.empty()){
        arrived = pq.top().idx;
        fuel-=pq.top().val;
        tx = p[arrived][3];
        ty = p[arrived][2];
        break;
    }
    return arrived;
}

int main() {
    ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
    cin >> num>>mv>>fuel;
    for(int i=1;i<=num;i++)
        for(int j=1;j<=num;j++)
            cin >> arr[i][j];
    for(int i=1;i<=mv;i++)
        need_fuel[i]=MAX;
    cin >> ty>>tx;
    for(int i=1;i<=mv;i++){
        cin>>p[i][0]>>p[i][1]>>p[i][2]>>p[i][3];
        people[p[i][0]][p[i][1]]=i;
    }

    int cnt=0;      //데려다 준 사람 수
    cal();
    while(cnt<mv){
        int pidx = mvToPeople();
        if(pidx==-1){
            fuel = pidx;
            break;
        }
        if(fuel>=need_fuel[pidx]){
            fuel+=need_fuel[pidx];
            cnt++;
            finish[pidx]=true;
        }
        else{
            fuel = -1;
            break;
        }
    }
    cout << fuel;
    return 0;
}
728x90
반응형

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

[백준 8983] 사냥꾼 (C++)  (0) 2021.02.23
[백준 2352] 반도체 설계 (C++)  (0) 2021.02.23
[백준 2812] 크게 만들기 (C++)  (0) 2021.02.19
[백준 14267] 회사 문화 1 (C++)  (0) 2021.02.18
[백준 2660] 회장뽑기 (C++)  (0) 2021.02.10
Comments