문제 풀이/백준

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

JJJaewon 2023. 9. 24. 17:40
반응형

 이 문제는 bfs를 이용해서 풀었다. 이 문제에서 핵심은 택시가 손님들을 찾는 과정에서 최단거리이며, 만약 거리가 같은 경우 행 번호가 작은, 행 번호도 같다면 열 번호가 작은 손님을 찾는 것이다. 이를 위해 처음에는 bfs의 상하좌우 탐색 순서를 상좌우하 순서로 탐색하고 찾은 경우를 리턴했지만, 이는 정답이 나오지 않았다. 그래서 두 번째 방법으로 일단 bfs를 맵 전체에 대해 돌리고, 손님들의 startY, startX를 기준으로 오름차순 정렬한 배열에 대해 최단거리를 비교하며 손님을 뽑는 형식으로 바꿔 정답을 도출해낼 수 있었다. 이 부분만 잘 해결한다면 나머지는 쉽게 구현 가능한 문제였다.

 

 

#include <iostream>
#include <vector>
#include <queue>
#include <utility>
#include <algorithm>

using namespace std;

struct passenger {
	int startY;
	int startX;
	int endY;
	int endX;
};

int N, M;
long long fuel;
int matrix[21][21];
int dy[] = { -1, 0, 0, 1 };
int dx[] = { 0, -1, 1, 0 };
vector<passenger> pass;
vector<vector<int>> dist;

bool inRange(int y, int x) {
	if (1 <= y && y <= N && 1 <= x && x <= N) {
		return true;
	}
	return false;
}

void findPassenger(int startY, int startX) {
	dist = vector<vector<int>>(N + 1, vector<int>(N + 1, 0));
	queue<pair<int, int>> q;

	q.push({ startY, startX });
	dist[startY][startX] = 1;

	while (!q.empty()) {
		pair<int, int> present = q.front();
		q.pop();

		for (int i = 0; i < 4; i++) {
			int ny = present.first + dy[i];
			int nx = present.second + dx[i];

			if (inRange(ny, nx) && dist[ny][nx] == 0 && matrix[ny][nx] != 1) {
				dist[ny][nx] = dist[present.first][present.second] + 1;
				q.push({ ny, nx });
			}
		}
	}
}

int movePassenger(int startY, int startX, int endY, int endX) {
	vector<vector<int>> visited(N + 1, vector<int>(N + 1, 0));
	queue<pair<int, int>> q;

	q.push({ startY, startX });
	visited[startY][startX] = 1;

	while (!q.empty()) {
		pair<int, int> present = q.front();
		q.pop();

		if (present.first == endY && present.second == endX) {
			return visited[present.first][present.second] - 1;
		}

		for (int i = 0; i < 4; i++) {
			int ny = present.first + dy[i];
			int nx = present.second + dx[i];

			if (inRange(ny, nx) && visited[ny][nx] == 0 && matrix[ny][nx] != 1) {
				visited[ny][nx] = visited[present.first][present.second] + 1;
				q.push({ ny, nx });
			}
		}
	}

	return -1;
}

bool compare(passenger &a, passenger &b) {
	if (a.startY == b.startY) {
		return a.startX < b.startX;
	}
	return a.startY < b.startY;
}

int main() {
	ios_base::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);

	cin >> N >> M >> fuel;

	for (int y = 1; y <= N; y++) {
		for (int x = 1; x <= N; x++) {
			cin >> matrix[y][x];
		}
	}

	int startY, startX;

	cin >> startY >> startX;

	for (int i = 1; i <= M; i++) {
		int sy, sx, ey, ex;

		cin >> sy >> sx >> ey >> ex;

		pass.push_back({ sy, sx, ey, ex });
	}

	sort(pass.begin(), pass.end(), compare);

	for (int i = 0; i < M; i++) {
		// 1. move to passenger
		findPassenger(startY, startX);

		passenger result = { -1, -1, -1, -1 };
		int index = -1;
		int tempDist = 1000000;

		for (int i = 0; i < pass.size(); i++) {
			passenger temp = pass[i];
			int distance = dist[temp.startY][temp.startX];

			if (distance > 0) {
				if (tempDist > distance) {
					tempDist = distance;
					result = temp;
					index = i;
				}
			}
		}

		tempDist--;

		if (index == -1) {
			cout << -1 << '\n';
			return 0;
		}

		pass.erase(pass.begin() + index);

		if (fuel - tempDist < 0) {
			cout << -1 << '\n';
			return 0;
		}
		fuel -= tempDist;

		startY = result.startY;
		startX = result.startX;
		int endY = result.endY;
		int endX = result.endX;

		// 2. move to destination
		tempDist = movePassenger(startY, startX, endY, endX);

		if (tempDist == -1) {
			cout << -1 << '\n';
			return 0;
		}

		if (fuel - tempDist < 0) {
			cout << -1 << '\n';
			return 0;
		}

		fuel += tempDist;
		startY = endY;
		startX = endX;
	}

	cout << fuel << '\n';

	return 0;
}
반응형