[백준] [C++] 🚓 경찰차 2618번
💡 문제 설명

동적 계획법 + 최단거리 역추적 문제이다.
💡 C++ 풀이
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
/*
dp[i][i]
경찰차 1이 마지막으로 i번째 사건 해결,
경찰차 2가 마지막으로 j번째 사건 해결했을 경우
총 거리의 합의 최소값 저장
*/
int N, M;
pii accident[1001], before[1001][1001];
int dp[1001][1001];
int dist(int car, int start, int end){
if (start==0){
if (car==1){
return accident[end].first-1 + accident[end].second-1;
}
else {
return N-accident[end].first + N-accident[end].second;
}
}
// c++17 부터 가능 auto unpacking
auto [x1, y1] = accident[start];
auto [x2, y2] = accident[end];
return abs(x1-x2)+abs(y1-y2);
}
void backtrace (int x, int y) {
if (x==0 && y==0) return;
int nx = before[x][y].first;
int ny = before[x][y].second;
backtrace(nx, ny);
if (x>y) cout << "1\n";
else cout << "2\n";
}
int main(){
ios_base::sync_with_stdio(0); cin.tie(0);
cin >> N >> M;
for (int i=1; i<=M; i++){
cin >> accident[i].first >> accident[i].second;
}
// dp 초기화
for(int i=0; i<=M; i++){
for (int j=0; j<=M; j++){
dp[i][j] = 1e9;
}
}
dp[0][0]=0;
// 처음에 시작점에서 이동하는 경우만 따로 해줘야함
for (int end=1; end<=M; end++){
// end-1을 경찰차1이 방문한 경우
for (int car2=0; car2<=end-1; car2++){
// end를 경찰차1이 또 방문
int dist11 = dp[end-1][car2] + dist(1, end-1, end);
if (dist11<dp[end][car2]){
dp[end][car2] = dist11;
before[end][car2] = {end-1, car2};
}
// end를 경찰차2가 방문
int dist12 = dp[end-1][car2] + dist(2, car2, end);
if(dist12 < dp[end-1][end]){
dp[end-1][end] = dist12;
before[end-1][end] = {end-1, car2};
}
}
// end-1을 경찰차2이 방문한 경우
for (int car1=0; car1<=end-1; car1++){
// end를 경찰차2가 또 방문
int dist22 = dp[car1][end-1] + dist(2, end-1, end);
if(dist22<dp[car1][end]){
dp[car1][end] = dist22;
before[car1][end] = {car1, end-1};
}
// end를 경찰차1이 방문
int dist21 = dp[car1][end-1] + dist(1, car1, end);
if(dist21 < dp[end][end-1]){
dp[end][end-1] = dist21;
before[end][end-1] = {car1, end-1};
}
}
}
// 최대값 찾기
int ans = 1e9;
pii idx;
for(int i=0; i<M; i++){
if (dp[M][i] < ans){
ans = dp[M][i];
idx = {M,i};
}
if (dp[i][M] < ans){
ans = dp[i][M];
idx = {i,M};
}
}
cout << ans << '\n';
backtrace(idx.first, idx.second);
return 0;
}
💡 마무리
DP 플래티넘 문제 치곤 도움 없이 혼자 잘 풀어냈다. backtrace는 생각보다 재밌는것 같다.