본문 바로가기

c++/Baekjoon Online

백준 19238 : 스타트 택시 c++

www.acmicpc.net/problem/19238

 

19238번: 스타트 택시

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

www.acmicpc.net

전체 풀이

1. 택시를 taxi라는 struct 하나 만들고 그걸로 관리

2. 손님을 지금 위치랑 목적지 함께 저장해서 vector에 저장해둠

 -> 후에 이 벡터가 다 비면 모든 손님 다 대려다줬다는거임

3. while문 돌리기

 1) 처음에 택시에서 제일 위치 가깝고, 행 제일 작고, 열 제일 작은놈 찾음

 2) 택시 거기로 이동 시키고 연료도 그만큼 깎음

  - 가다가 연료 바닥나면 -1 출력하고 return 0

 3) 이제 목적지까지 거리 구하고  이동 시킴

  - 가다가 연료 바닥나면 -1 출력하고 return 0 

 4) 연료 충전

 5) 모든 손님 태웠으면 루프 나오기

 

필요한 구현

1. 거리구하기 - BFS 기본 

 -> 모든 경우 me에서 목적지까지니까 인자는 목적지의 좌표만 받음

2. 이동할때 마다 택시 위치 업데이트

3. 중간에 못 도착하는 경우 flag 를 -1로 변환

 -> 벽에 막혀서 아예 도착을 못하는 경우

 -> 기름이 부족한 경우

 

 

 

#include <iostream>
#include <vector>
#include <queue>
#include <cmath>
#include <cstring>
using namespace std;

struct taxi {
	int r, c, fuel;
	//지금 위치랑 연료!
};
struct customer {
	int start_r, start_c;
	int end_r, end_c;
};

int d_r[4] = { 1,-1,0,0 };
int d_c[4] = { 0,0,1,-1 };

taxi me;
vector<customer> customers;
int how_far = 987654321;
int go_to;

int n, m;
int map[21][21];
int visited[21][21];
int flag = 0;

int bfs(int new_r, int new_c)//me 에서부터 목적지!
{
	memset(visited, 0, sizeof(visited));

	if (me.r == new_r && me.c == new_c)//목적지랑 지금위치랑 똑같을때!!
	{
		return 0;
	}

	visited[me.r][me.c] = 1;
	queue<pair<int, int> > q;
	q.push(make_pair(me.r, me.c));

	int result = 0;
	while (!q.empty())
	{
		int s = q.size();
		for (int j = 0; j < s; j++)
		{
			int r = q.front().first;
			int c = q.front().second;
			q.pop();
			for (int i = 0; i < 4; i++)
			{
				int new_rr = r + d_r[i];
				int new_cc = c + d_c[i];
				if (new_rr <= 0 || new_cc <= 0 || new_rr > n || new_cc > n)
					continue;
				if (visited[new_rr][new_cc] == 1)
					continue;
				if (map[new_rr][new_cc] == 1)//벽
					continue;

				if (new_rr == new_r && new_cc == new_c)//목적지
					return result + 1;

				visited[new_rr][new_cc] = 1;
				q.push(make_pair(new_rr, new_cc));
			}

		}
		result++;
	}

	return -1;//갈수 없는 경우
}

void find_shortest()
{

	for (int i = 0; i < customers.size(); i++)
	{
		int sum = bfs(customers[i].start_r, customers[i].start_c);
		if (sum == -1)//갈수 없음!!
		{
			flag = 1;
			return;
		}
		else if (how_far > sum)
		{
			//더 짧으면
			how_far = sum;
			go_to = i;
		}
		else if (how_far == sum)
		{
			if (customers[go_to].start_r > customers[i].start_r)
			{
				go_to = i;
			}
			else if (customers[go_to].start_r == customers[i].start_r)
			{
				if (customers[go_to].start_c > customers[i].start_c)
					go_to = i;
			}
		}
	}
}

int main()
{
	cin >> n >> m >> me.fuel;

	for(int i=1;i<=n;i++)
		for (int j = 1; j <= n; j++)
		{
			cin >> map[i][j];//1이 벽
		}
	cin >> me.r >> me.c;
	for (int i = 0; i < m; i++)
	{
		customer a;
		cin >> a.start_r >> a.start_c >> a.end_r >> a.end_c;
		customers.push_back(a);
	}

	while (true)//연료 떨어지거나, 모두 다 채웠으면 나갈꺼임
	{
		how_far = 987654321;
		find_shortest();
		//손님까지의 거리 how_far
		//어디 손님? go_to

		if (flag == -1)//갈수 없는 곳이 있음!!
		{
			cout << -1 << endl;
			return 0;
		}

		if (me.fuel < go_to)//가야되는 거리보다 연료가 더 많이 필요
		{
			cout << -1 << endl;
			return 0;
		}

		me.fuel = me.fuel - how_far;

		me.r = customers[go_to].start_r;
		me.c = customers[go_to].start_c;


		how_far = 987654321;
		how_far = bfs(customers[go_to].end_r, customers[go_to].end_c);

		if (how_far == -1)//갈수 없는 길이면!
		{
			cout << -1 << endl;
			return 0;

		}
		if (how_far > me.fuel)
		{
			//목적지까지 못가여...ㅜㅜ
			cout << -1 << endl;
			return 0;
		}
		//무사히 대려다줌
		me.fuel = me.fuel - how_far;
		me.r = customers[go_to].end_r;
		me.c = customers[go_to].end_c;
		customers.erase(customers.begin() + go_to);

		

		me.fuel += how_far * 2;
		if (customers.size() == 0)//한번은 무조건 하니까 조건 뒤에 해도 됨염
			break;
	}

	cout << me.fuel << endl;
	return 0;
}

'c++ > Baekjoon Online' 카테고리의 다른 글

백준 1938 : 통나무 옮기기 c++  (0) 2020.10.16
백준 19237 : 어른 상어 C++  (0) 2020.10.15
백준 17142 c++ : 연구소 3  (0) 2020.10.11
백준 1726 : 로봇 c++  (0) 2020.10.10
백준 11559 : Puyo Puyo c++  (0) 2020.10.10