fragment-header
fragment-markdown
홈
로그인
로그아웃
내 블로그
설정
로그인
백준 2618 (C++) 경찰차
최초 업로드: 2025-04-20 10:11:08
최근 수정 시간: 2025-07-25 09:30:13
게시자: rlatjwls3333
카테고리: 백준
조회수: 9
# [Platinum IV] 경찰차 #### [문제 링크](https://www.acmicpc.net/problem/2618) ## 문제 설명 <p>어떤 도시의 중심가는 N개의 동서방향 도로와 N개의 남북방향 도로로 구성되어 있다.</p> <p>모든 도로에는 도로 번호가 있으며 남북방향 도로는 왼쪽부터 1에서 시작하여 N까지 번호가 할당되어 있고 동서방향 도로는 위부터 1에서 시작하여 N까지 번호가 할당되어 있다. 또한 동서방향 도로 사이의 거리와 남 북방향 도로 사이의 거리는 모두 1이다. 동서방향 도로와 남북방향 도로가 교차하는 교차로의 위치는 두 도로의 번호의 쌍인 (동서방향 도로 번호, 남북방향 도로 번호)로 나타낸다. N이 6인 경우의 예를 들면 다음과 같다.</p> <p style="text-align: center;"><img alt="" src="https://upload.acmicpc.net/6b5a6518-1801-46c9-9b17-49e8abb3bc88/-/preview/" style="width: 207px; height: 170px;"></p> <p>이 도시에는 두 대의 경찰차가 있으며 두 차를 경찰차1과 경찰차2로 부른다. 처음에는 항상 경찰차1은 (1, 1)의 위치에 있고 경찰차2는 (N, N)의 위치에 있다. 경찰 본부에서는 처리할 사건이 있으면 그 사건이 발생된 위치를 두 대의 경찰차 중 하나에 알려 주고, 연락 받은 경찰차는 그 위치로 가장 빠른 길을 통해 이동하여 사건을 처리한다. (하나의 사건은 한 대의 경찰차가 처리한다.) 그리고 사건을 처리 한 경찰차는 경찰 본부로부터 다음 연락이 올 때까지 처리한 사건이 발생한 위치에서 기다린다. 경찰 본부에서는 사건이 발생한 순서대로 두 대의 경찰차에 맡기려고 한다. 처리해야 될 사건들은 항상 교차로에서 발생하며 경찰 본부에서는 이러한 사건들을 나누어 두 대의 경찰차에 맡기되, 두 대의 경찰차들이 이동하는 거리의 합을 최소화 하도록 사건을 맡기려고 한다.</p> <p>예를 들어 앞의 그림처럼 N=6인 경우, 처리해야 하는 사건들이 3개 있고 그 사건들이 발생된 위치 를 순서대로 (3, 5), (5, 5), (2, 3)이라고 하자. (3, 5)의 사건을 경찰차2에 맡기고 (5, 5)의 사건도 경찰차2에 맡기며, (2, 3)의 사건을 경찰차1에 맡기면 두 차가 이동한 거리의 합은 4 + 2 + 3 = 9가 되 고, 더 이상 줄일 수는 없다.</p> <p>처리해야 할 사건들이 순서대로 주어질 때, 두 대의 경찰차가 이동하는 거리의 합을 최소화 하도록 사건들을 맡기는 프로그램을 작성하시오.</p> ## 입력 <p>첫째 줄에는 동서방향 도로의 개수를 나타내는 정수 N(5 ≤ N ≤ 1,000)이 주어진다. 둘째 줄에는 처리해야 하는 사건의 개수를 나타내는 정수 W(1 ≤ W ≤ 1,000)가 주어진다. 셋째 줄부터 (W+2)번째 줄까지 사건이 발생된 위치가 한 줄에 하나씩 주어진다. 경찰차들은 이 사건들을 주어진 순서대로 처리해야 한다. 각 위치는 동서방향 도로 번호를 나타내는 정수와 남북방향 도로 번호를 나타내는 정수로 주어지며 두 정수 사이에는 빈칸이 하나 있다. 두 사건이 발생한 위치가 같을 수 있다.</p> ## 출력 <p>첫째 줄에 두 경찰차가 이동한 총 거리를 출력한다. 둘째 줄부터 시작하여 (i+1)번째 줄에 i(1 ≤ i ≤ W)번째 사건이 맡겨진 경찰차 번호 1 또는 2를 출력한다.</p> ## 풀이 #### dp[a][b]를 1번 경찰차가 a번 위치에, 2번 경찰차가 b번 위치에 있을 때의 최소 비용으로 두고 다이너믹 프로그래밍을 쓰면 된다. ``` c++ #include<bits/stdc++.h> using namespace std; const int S1=0, S2=1; // S1 : 1번 경찰차의 위치, S2 : 2번 경찰차의 위치 int n, w; int pos[1002][2]; // 순찰할 위치 int dp[1002][1002]; // dp[a][b] : 1번 순찰차는 a 위치에, 2번 순찰차는 b 위치에 있을 때의 최소 비용 int trace[1002][1002]; // 역추적 int getCost(int cur, int next) { // 이동 비용 return abs(pos[cur][0]-pos[next][0]) + abs(pos[cur][1]-pos[next][1]); } int solve(int a, int b) { if(dp[a][b]!=-1) return dp[a][b]; if(a==w+1 || b==w+1) return 0; int next = max(a, b)+1; // 1번 순찰차가 이동 (pos[a]에서 pos[next]로 이동) int nextCost1 = solve(next, b) + getCost(a, next); // 2번 순찰차가 이동 (pos[b]에서 pos[next]로 이동) int nextCost2 = solve(a, next) + getCost(b, next); if(nextCost1<nextCost2) { trace[a][b]=1; dp[a][b] = nextCost1; } else { trace[a][b]=2; dp[a][b] = nextCost2; } return dp[a][b]; } int main() { ios::sync_with_stdio(0); cin.tie(0); cin >> n >> w; pos[S1][0]=pos[S1][1]=1; pos[S2][0]=pos[S2][1]=n; for(int i=2;i<w+2;i++) cin >> pos[i][0] >> pos[i][1]; memset(dp, -1, sizeof dp); solve(S1, S2); cout << dp[S1][S2] << '\n'; // 최소비용 // 역추적 for(int a=S1, b=S2;a!=w+1 && b!=w+1;) { cout << trace[a][b] << '\n'; if(trace[a][b]==1) a = max(a, b)+1; else b = max(a, b)+1; } } ```