공부/PS (백준)
[BOJ] 19238 스타트 택시 / C++
happyst
2022. 4. 28. 23:49
https://www.acmicpc.net/problem/19238
19238번: 스타트 택시
첫 줄에 N, M, 그리고 초기 연료의 양이 주어진다. (2 ≤ N ≤ 20, 1 ≤ M ≤ N2, 1 ≤ 초기 연료 ≤ 500,000) 연료는 무한히 많이 담을 수 있기 때문에, 초기 연료의 양을 넘어서 충전될 수도 있다. 다
www.acmicpc.net
#include <stdio.h>
#include <queue>
#include <vector>
#include <algorithm>
#define MAX_N 21
#define MAX_M 401
using namespace std;
int N, M, fuel;
int MAP[MAX_N][MAX_N]; // -2: EMPTY, -1:
int dist[MAX_N][MAX_N];
struct DRIVER {
int r, c, t;
};
DRIVER driver;
struct INFO {
int sr, sc, er, ec;
};
INFO info[MAX_M];
struct PASSENGER {
int r, c;
};
PASSENGER passenger[MAX_M];
vector <DRIVER> passengerList;
int dr[] = { -1,0,1,0 };
int dc[] = { 0,-1,0,1 };
bool flag = true; // 모든 승객이 목적지까지 도달할 수 있음
void input()
{
scanf("%d %d %d", &N, &M, &fuel);
for (int i = 1; i <= N; i++)
{
for (int j = 1; j <= N; j++)
{
scanf("%d", &MAP[i][j]);
MAP[i][j] -= 2;
}
}
scanf("%d %d", &driver.r, &driver.c);
for (int i = 1; i <= M; i++)
{
int sr, sc, er, ec;
scanf("%d %d %d %d", &sr, &sc, &er, &ec);
info[i] = { sr,sc,er,ec};
passenger[i] = { sr,sc};
MAP[sr][sc] = i; // MAP에 승객의 번호를 저장
}
}
void initialize_dist()
{
for (int i = 1; i <= N; i++)
{
for (int j = 1; j <= N; j++)
{
dist[i][j] = -1;
}
}
}
void print_dist()
{
printf("\n>> print_dist()\n");
for (int i = 1; i <= N; i++)
{
for (int j = 1; j <= N; j++)
{
printf("%2d ", dist[i][j]);
}
printf("\n");
}
}
void print_passengerList()
{
printf("\n>> print_passengerList()\n");
for (int i = 0; i < passengerList.size(); i++)
{
printf("[%d] r = %d, c = %d, t = %d\n", i, passengerList[i].r, passengerList[i].c, passengerList[i].t);
}
}
bool cmp(const DRIVER &p1, const DRIVER &p2)
{
if (p1.t < p2.t) return true;
else if (p1.t == p2.t)
{
if (p1.r < p2.r) return true;
else if (p1.r == p2.r)
{
return p1.c < p2.c;
}
}
return false;
}
void getShortestDist()
{
initialize_dist(); // dist 배열을 -1로 초기화
passengerList.clear(); // 승객 리스트 초기화
queue <DRIVER> q;
driver.t = 0; // 택시기사의 거리 초기화
dist[driver.r][driver.c] = 0;
q.push(driver);
while (!q.empty())
{
int cur_r = q.front().r;
int cur_c = q.front().c;
int cur_t = q.front().t;
q.pop();
for (int k = 0; k < 4; k++)
{
int nr = cur_r + dr[k];
int nc = cur_c + dc[k];
if (nr <= 0 || nr > N || nc <= 0 || nc > N || MAP[nr][nc] == -1 || dist[nr][nc] != -1) continue;
q.push({ nr,nc,cur_t + 1 });
dist[nr][nc] = cur_t + 1;
}
}
//print_dist();
for (int i = 1; i <= M; i++)
{
int r = passenger[i].r;
int c = passenger[i].c;
if (MAP[r][c] > 0)
{
if (dist[r][c] == -1) // 벽에 둘러싸인 승객이 존재
{
flag = false;
return;
}
else if (fuel > dist[r][c]) // 승객을 데려다줄 수 있으면
{
passengerList.push_back({ r,c,dist[r][c] });
}
}
}
if (passengerList.size() > 0)
{
sort(passengerList.begin(), passengerList.end(), cmp);
}
else
{
flag = false;
return;
}
//print_passengerList();
}
int choose_passenger()
{
// passengerList가 존재함
int r = passengerList[0].r;
int c = passengerList[0].c;
int passengerNum = MAP[r][c]; // 승객 번호
return passengerNum;
}
int drive(int passengerNum)
{
// 승객을 태우러 감
int pr = passenger[passengerNum].r;
int pc = passenger[passengerNum].c;
//printf("승객 태우기 전... fuel = %d\n", fuel);
fuel -= dist[pr][pc];
//printf("승객 태우러 왔음... fuel = %d\n", fuel);
if (fuel < 0)
{
return -1;
}
else
{
int er = info[passengerNum].er;
int ec = info[passengerNum].ec;
queue <DRIVER> q;
driver.r = pr;
driver.c = pc;
driver.t = 0;
initialize_dist();
dist[driver.r][driver.c] = 0;
q.push(driver);
while (!q.empty())
{
int cur_r = q.front().r;
int cur_c = q.front().c;
int cur_t = q.front().t;
q.pop();
if (cur_r == er && cur_c == ec)
{
//printf("승객 데려다줌~~!\n");
MAP[pr][pc] = -2; // 승객을 벽으로 바꿔줌
driver.r = er;
driver.c = ec; // 택시 기사 위치 업데이트
fuel -= cur_t;
//printf("fuel = %d\n", fuel);
if (fuel < 0) return -1;
else
{
fuel += (2 * cur_t);
return fuel;
}
}
for (int k = 0; k < 4; k++)
{
int nr = cur_r + dr[k];
int nc = cur_c + dc[k];
if (nr <= 0 || nr > N || nc <= 0 || nc > N || MAP[nr][nc] == -1 || dist[nr][nc] != -1) continue;
q.push({ nr,nc,cur_t + 1 });
dist[nr][nc] = cur_t + 1;
}
}
}
return -1;
}
int solve()
{
int ret = -1;
for (int i = 1; i <= M; i++)
{
flag = true;
// 1. 현재 택시기사의 위치에서 승객간의 최단거리를 구한다
getShortestDist();
if (flag == false) return -1; // 벽에 둘러싸인 승객이 있을때 -> 실패
// 2. 태우러 갈 승객의 번호를 정한다
int passengerNum = choose_passenger();
// 3. 승객을 목적지까지 데려다준다.
ret = drive(passengerNum);
if (ret == -1) return -1;
}
return ret;
}
int main(void)
{
input();
int answer = solve();
printf("%d\n", answer);
return 0;
}
이 문제도 주어진 테스트 케이스는 다 통과하는데 계속 틀렸습니다를 받았던 문제다.
알고보니 INFO info[MAX_M]으로 선언해야하는데 INFO info[MAX_N]으로 선언해서 버퍼 크기가 터져버렸던것..ㅎㅎ
제발 다시는 이런 실수 하지말자