반응형
Notice
Recent Posts
Recent Comments
Link
«   2024/07   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31
Archives
Today
Total
관리 메뉴

코딩하기 좋은날

백준 2618 경찰차 본문

백준(Baekjoon) 문제

백준 2618 경찰차

huiung 2020. 1. 19. 12:21
반응형

DP  문제입니다. 

 

이전에 풀었던 환상의 듀엣 이란 문제와 유사한데 경찰차가 이동하는 지점이 반드시 정해져 있습니다.

 

즉 두 경찰차는 반드시 시작지점이 아니면 사건이 발생한 어느지점에 위치하고 있기 때문에 DP 배열을 아래와 같이 정의 할 수 있습니다.

DP[i][j] = 1번 경찰차가 마지막으로 해결한사건(i), 2번 경찰차가 마지막으로 해결한사건(j) 일때의 최소 이동거리

 

저렇게 정의한다면 우리는 max(i,j) + 1이 다음사건임을 알 수 있습니다. 

 

이 문제는 여기서 끝이 아니라 이 최소비용을 얻었을때 각 사건을 어떤 경찰차가 해결하였는지 까지 출력을 하여야 합니다. 처음에 이 경로를 어떻게 구해야 할지 생각이 안났는데 먼저 최소 비용을 구한 후 다시 0,0 부터 시작하며 자신이 선택한 경로를 따라가면 쉽게 찾을 수 있습니다. 각 함수에서 1번이 해결한 경우 / 2번이 해결한 경우로 나뉘는데 이 두값중 우리는 작은 값을 택하면서 내려왔으므로 작은 값을 택하는 경우를 찾아서 다시 올라가면 됩니다!

 

말보다는 아무래도 코드로 보시면 이해가 쉬울 것 같습니다.

 

#include <iostream>
#include <vector>
#include <cstring>
#include <algorithm>
#include <stack>

#define INF 987654321
using namespace std;

vector<pair<int, int> > pr;

int dp[1010][1010]; //i: 1번 경찰차가 마지막으로 방문한 곳 j: 2번 경찰차가 마지막 방문 했을때 최소값

int N;
int w;
int ans = INF;
stack<int> s;

int sol(int first, int second) {
	
	if (first == w || second == w) {
		
		return 0;
	}

	int &ret = dp[first][second];
	if (ret != -1) return ret;

	int next = max(first, second) + 1; //다음 사건
	int dist1, dist2;
	
	if(first == 0) dist1 = abs(pr[next - 1].first - 1) + abs(pr[next - 1].second -1);
	else dist1 = abs(pr[next - 1].first - pr[first - 1].first) + abs(pr[next - 1].second - pr[first - 1].second);

	if(second == 0) dist2 = abs(pr[next - 1].first - N) + abs(pr[next - 1].second - N);
	else dist2 = abs(pr[next - 1].first - pr[second - 1].first) + abs(pr[next - 1].second - pr[second - 1].second);


	int left = sol(next, second) + dist1;
	int right = sol(first, next) + dist2;

	ret = min(left, right);

	return ret;
}



void back(int first, int second) {
	
	if (first == w || second == w) {
		return;
	}

	int next = max(first, second) + 1; //다음 사건
	int dist1, dist2;

	if (first == 0) dist1 = abs(pr[next - 1].first - 1) + abs(pr[next - 1].second - 1);
	else dist1 = abs(pr[next - 1].first - pr[first - 1].first) + abs(pr[next - 1].second - pr[first - 1].second);

	if (second == 0) dist2 = abs(pr[next - 1].first - N) + abs(pr[next - 1].second - N);
	else dist2 = abs(pr[next - 1].first - pr[second - 1].first) + abs(pr[next - 1].second - pr[second - 1].second);


	if (dp[next][second] + dist1 > dp[first][next] + dist2) {
		cout << 2 << '\n';
		back(first, next);
	}
	else {
		cout << 1 << '\n';
		back(next, second);
	}
	return;
}


int main(void) {
	ios_base::sync_with_stdio(false); cin.tie(NULL);
	memset(dp, -1, sizeof(dp));
	cin >> N; 
	cin >> w;

	for (int i = 0; i < w; i++) {
		int x, y; cin >> x >> y;
		pr.push_back({ x,y });
	}	

	cout << sol(0, 0) << '\n';
	back(0, 0);
	return 0;
}
반응형

'백준(Baekjoon) 문제' 카테고리의 다른 글

백준 7578 공장  (0) 2020.01.19
백준 1102 발전소  (0) 2020.01.19
백준 파이프 옮기기 2  (0) 2019.11.10
백준 17135 캐슬 디펜스  (0) 2019.11.10
백준 12920 평범한 배낭2  (0) 2019.11.08