# 문제링크
19238번: 스타트 택시
첫 줄에 N, M, 그리고 초기 연료의 양이 주어진다. (2 ≤ N ≤ 20, 1 ≤ M ≤ N2, 1 ≤ 초기 연료 ≤ 500,000) 연료는 무한히 많이 담을 수 있기 때문에, 초기 연료의 양을 넘어서 충전될 수도 있다. 다
www.acmicpc.net
그 아기상어 문제를 풀고 난 뒤부터, 대부분 BFS 문제가 아기상어 문제처럼 보인다. 이것도 BFS로 손님 찾고 visit 초기화, BFS로 목적지 데려다주고 visit 초기화. 이런 식으로 진행된다. 손님을 찾는 BFS에서 손님 번호를 return 해야 하는데, 동시에 손님까지 간 거리도 return 해주고 싶었다. 왜냐면 solve 함수에서 taxi 관련 데이터를 처리하고싶었기 때문이다. 그래서 user_distance 라는 전역 변수를 둬서 거기에 저장해주고, 손님 번호를 리턴했다. 야매 처리방법~! ㅎㅎ
함정은 택시와 승객이 같은 위치에 있을 경우이다. 문제에서도 같은 위치에 서있으면 최단거리 0이라고 힌트를 주긴 했다 ㅎ BFS 두개 만드니 코드도 길고 현타도 씨게 온다..
# 제출 코드
#include <cstdio>
#include <queue>
#include <algorithm>
#include <vector>
#include <cstring>
using namespace std;
int N, M, F;
int map[21][21];
int visited[21][21];
int user_map[21][21];
struct st {
	int uy;
	int ux;
	int dy;
	int dx;
};
st user[401];
struct TAXI {
	int y;
	int x;
	int f;
};
TAXI taxi;
int yd[] = { 1, -1 ,0,0 };
int xd[] = { 0, 0, 1, -1 };
void Input(){
	scanf("%d %d %d", &N, &M, &taxi.f);
	for (int i = 1; i <= N; i++) {
		for (int j = 1; j <= N; j++) {
			scanf("%d", &map[i][j]);
		}
	}
	scanf("%d %d", &taxi.y, &taxi.x);
	int uy, ux, dy, dx;
	for (int i = 1; i <= M; i++) {
		scanf("%d %d %d %d", &user[i].uy, &user[i].ux, &user[i].dy, &user[i].dx);
		user_map[user[i].uy][user[i].ux] = i; // 사용자 위치 체크맵
	}
}
int user_distance = 0;
int FindUser(int y, int x) {
	vector<pair<int, int>> u;
	queue<pair<int, int>> q;
	q.push({ y,x });
	visited[y][x] = 1;
	int time = 1;
	if (user_map[y][x] != 0) { // 택시와 손님이 같은 위치에 있을 경우
		user_distance = 0;
		int ret = user_map[y][x];
		user_map[y][x] = 0;
		return ret;
	}
	while (!q.empty()) {
		int y = q.front().first;
		int x = q.front().second;
		q.pop();
		if (time != visited[y][x]) {
			if (u.size()) {
				sort(u.begin(), u.end());
				user_distance = time;
				int ret = user_map[u[0].first][u[0].second];
				user_map[u[0].first][u[0].second] = 0; // 선택된 user 맵에서 지우기 
				return ret;
			}
			time = visited[y][x];
		}
		for (int i = 0; i < 4; i++) {
			int ny = y + yd[i];
			int nx = x + xd[i];
			if (ny < 1 || ny > N)continue;
			if (nx < 1 || nx > N)continue;
			if (visited[ny][nx] != 0)continue; // 이미 방문
			if (map[ny][nx] == 1)continue; // 벽
			if (user_map[ny][nx] != 0) u.push_back({ ny, nx }); // 손님?
			visited[ny][nx] = visited[y][x] + 1;
			q.push({ ny,nx });
		}
	}
	return -1;
}
int Move(int dy, int dx) {
	queue <pair<int, int>> q;
	q.push({ taxi.y, taxi.x });
	visited[taxi.y][taxi.x] = true;
	while (!q.empty()) {
		int y = q.front().first;
		int x = q.front().second;
		q.pop();
		for (int i = 0; i < 4; i++) {
			int ny = y + yd[i];
			int nx = x + xd[i];
			if (ny < 1 || ny > N)continue; //범위 
			if (nx < 1 || nx > N)continue;
			if (visited[ny][nx] != 0)continue; // 방문했던 곳 
			if (map[ny][nx] == 1)continue; // 벽이당
			if (ny == dy && nx == dx) return visited[y][x]; // 찾았다 목적지!!
			visited[ny][nx] = visited[y][x] + 1;
			q.push({ ny, nx });
		}
	}
	return -1;
}
int Solve() {
	for (int i = 0; i < M; i++) {
		user_distance = -1; // 손님까지 거리저장
		memset(visited, 0, sizeof(visited));
		
		int num = FindUser(taxi.y, taxi.x); // 손님 찾아서 번호 리턴 
		if (num == -1) return -1;
		taxi.f -= user_distance;
		taxi.y = user[num].uy;
		taxi.x = user[num].ux;
		if (taxi.f < 0) return -1;
		memset(visited, 0, sizeof(visited));
		int dest = Move(user[num].dy, user[num].dx); // 목적지까지 움직이고 거리 리턴 
		if (dest == -1) return -1;
		if (taxi.f - dest < 0) return -1;
		taxi.f = taxi.f + dest;
		taxi.y = user[num].dy;
		taxi.x = user[num].dx;
	}
	return taxi.f;
}
int main() {
	Input();
	printf("%d", Solve());
}

반응형
    
    
    
  'Computer Science&Engineering > 코딩테스트' 카테고리의 다른 글
| [ 백준 17136 ] 색종이 붙이기 (C++) (0) | 2021.04.24 | 
|---|---|
| [ 백준 12886 ] 돌 그룹 (C++) (0) | 2021.04.24 | 
| [ 백준 9207 ] 페그 솔리테어 (C++) (0) | 2021.04.21 | 
| [ 백준 17281 ] ⚾ 야구 구현 문제 (0) | 2021.04.20 | 
| [백준 9205] 맥주 마시면서 걸어가기 (C++) DFS, BFS 풀이 (0) | 2021.04.19 | 
 
									
								 
									
								 
									
								