[C++] 백준 19248 : 스타트 택시

Kim Nahyeong·2022년 10월 12일
0

백준

목록 보기
151/157

#include <iostream>
#include <queue> // BFS
#include <cstring> // memset
#include <utility> // pair

using namespace std;

int N, M;
int A[21][21]; // 0은 빈칸, 1은 벽
int temp[21][21] = {0}; // 거리 맵에 임시 저장 

struct INFO {
  int x, y;
  int destX, destY;
  bool moved = false; // 승객 목적지 도착 여부
};

INFO p[401]; // 승객 정보 저장

struct CAR {
  int x, y;
  int gas;
};

CAR car; // 자동차 정보 저장

queue<pair<int, int> > q; // BFS 탐색할 자동차 정보 저장 - CAR 정보 저장 x

int dx[4] = {-1, 1, 0, 0};
int dy[4] = {0, 0, -1, 1};

// 택시에서부터 거리 구하는 BFS
void BFS(){
  memset(temp, -1, sizeof(temp)); // temp 초기화
  q.push({car.y, car.x}); // 자동차 좌표 저장
  temp[car.y][car.x] = 0; // 방문 못한 곳 체크 위해서 

  while(!q.empty()){
    int y = q.front().first;
    int x = q.front().second;
    q.pop();

    for(int i = 0; i < 4; i++){
      int nx = x + dx[i];
      int ny = y + dy[i];

      // 범위 벗어나는 경우
      if(nx < 1 || ny < 1 || nx > N || ny > N){
        continue;
      }

      // 방문되지 않았고 벽이 아니면
      if(temp[ny][nx] == -1 && A[ny][nx] != -1){
        temp[ny][nx] = temp[y][x] + 1; // cnt 변수 쓰지 않고 전 값 사용
        q.push({ny, nx});
      }
    }
  }
}

int main(){
  scanf("%d %d %d", &N, &M, &car.gas);

  for(int i = 1; i <= N; i++){
    for(int j = 1; j <= N; j++){
      scanf("%d", &A[i][j]);

      // 손님 번호 맵에 저장 위해서 벽 -1로 변경
      if(A[i][j] == 1){
        A[i][j] = -1;
      }
    }
  }

  // 자동차, 행 / 렬 주어짐
  scanf("%d %d", &car.y, &car.x);

  for(int i = 1; i <= M; i++){
    // 각 승객의 출발지의 행과 열 번호, 그리고 목적지의 행과 열 번호
    scanf("%d %d %d %d", &p[i].y, &p[i].x, &p[i].destY, &p[i].destX);
    A[p[i].y][p[i].x] = i; // 현재 고객 위치 맵에 저장
  }

  // 승객 수만큼만 왔다갔다하면 됨
  for(int j = 1; j <= M; j++){
    // 자동차에서부터 맵 전체 거리 구하기
    BFS();
    // 가장 가까운 승객 구하기
    int minIdx = 0;
    int minDistance = 99999999;

    for(int i = 1; i <= M; i++){
      // 이미 도착지까지 이동된 손님이면 패스
      if(p[i].moved){
        continue;
      }

      int py = p[i].y;
      int px = p[i].x;

      // 승객 거리 가장 작은 것 구함
      if(temp[py][px] < minDistance){
        minIdx = i;
        minDistance = temp[py][px];
      } else if(temp[py][px] == minDistance){
        // 거리 같은 경우, 행번호 작은 승객 먼저, 그 다음에는 열번호 작은 승객
        if(p[minIdx].y > py){
          minIdx = i;
        } else if(p[minIdx].y == py && p[minIdx].x > px){
          minIdx = i;
        }
      }    
    }

    // 고객태우기
    int px = p[minIdx].x; // 고객 좌표
    int py = p[minIdx].y;
    int pdx = p[minIdx].destX;
    int pdy = p[minIdx].destY;

    car.x = px;
    car.y = py;

    // 승객에게 갈 수 없는 경우
    if(temp[py][px] == -1){
      printf("-1");
      return 0;
    }
    car.gas -= temp[py][px]; // 승객까지의 거리만큼 가스 없어짐

    // 연료 없는 경우
    if(car.gas < 0){
      printf("-1");
      return 0;
    }

    // 자동차로부터 모든 칸의 거리 구하기
    BFS();

    // 목적지로 갈 수 없는 경우
    if(temp[pdy][pdx] == -1){
      printf("-1");
      return 0;
    }

    // 자동차 목적지로 이동
    car.gas -= temp[pdy][pdx];

    // 자동차 연료 부족하면 끝
    if(car.gas < 0){
      printf("-1");
      return 0;
    }

    // 연료 부족하지 않은 경우
    car.x = pdx; car.y = pdy;
    car.gas += temp[pdy][pdx] * 2; // 연료 이동거리 2배 충전
    p[minIdx].moved = true; // 승객 이동 체크
  }
  printf("%d", car.gas);

  return 0;
}

와 진짜 y, x 잘 못 써서 2시간 헤맸다. 너무 힘들었음.
수명이 깎임....

  • 문제에서 열, 행 순서로 좌표를 준다. 조심하기

  • BFS를 계산할 때 queue에 CAR 구조체를 넣어주면 이상하게 꼬인다. 그냥 원래 쓰던대로 pair를 쓰던가 아니면 queue를 위한 구조체를 새로 만들어 쓰자.

  • 벽과 손님 숫자를 구별하기 위해 벽은 -1로 재저장시켜야한다.

  • BFS 계산시 방문한 지점과 방문하지 않은 지점을 구별하기 위해 초깃값을 -1로 지정한다. 그리고 택시가 존재하는 곳의 거리를 0으로 두어 BFS 탐색을 시작해준다.

0개의 댓글