[백준(BOJ)] 경찰차(2618번)_C++
2023. 3. 30. 20:29ㆍProblem Solving/DP
728x90
반응형
SMALL
어려움.
처음엔 dp[2][1001] 배열로 1이 움직일 때와 2가 움직일 때를 dp로 구현하려 했다.
문제점은 사건을 진행할 때마다 변경되는 각 경찰차의 위치와 사건진행 순서를 관리하기 어렵다는 것이었다.
그러다 기가막힌 방법을 하나 어디서 주워들었다.
dp[i][j] 가 1이 i번 사건까지 2는 j번 사건까지 해결했을 때의 최소 거리임을 의미하는 dp[1001][1001] 배열을 만드는 것이다.
즉, 각 경찰차가 마지막으로 진행한 사건 번호를 저장하는 것이었다. 그러면 굳이 좌표를 저장할 필요가 없었다.
dfs를 진행하면서 최소 거리를 찾으면서 dp 배열을 채운다.
각 경찰차의 사건 진행 순서도 비슷한 로직으로 구현할 수 있다.
이미 구해진 dp 배열을 이용해서 순서를 구할 수 있다.
코드를 조금씩 분석해보면서 이해해보기를 바란다.
정답
#include <iostream>
#include <cstring>
using namespace std;
int n, w;
pair<int, int> event[1001];
int dp[1001][1001];
int dfs(int p1, int p2){
//last event
if (p1 == w || p2 == w)
return 0;
//already calculate
if (dp[p1][p2] != -1)
return dp[p1][p2];
int next = max(p1, p2) + 1;
int dist1, dist2;
if (p1 == 0)
dist1 = abs(1 - event[next].first) + abs(1 - event[next].second);
else
dist1 = abs(event[p1].first - event[next].first) + abs(event[p1].second - event[next].second);
if (p2 == 0)
dist2 = (n - event[next].first) + (n - event[next].second);
else
dist2 = abs(event[p2].first - event[next].first) + abs(event[p2].second - event[next].second);
int res1 = dfs(next, p2) + dist1;
int res2 = dfs(p1, next) + dist2;
dp[p1][p2] = min(res1, res2);
return dp[p1][p2];
}
void print_order(int p1, int p2){
if (p1 == w || p2 == w)
return ;
int next = max(p1, p2) + 1;
int dist1, dist2;
if (p1 == 0)
dist1 = abs(1 - event[next].first) + abs(1 - event[next].second);
else
dist1 = abs(event[p1].first - event[next].first) + abs(event[p1].second - event[next].second);
if (p2 == 0)
dist2 = (n - event[next].first) + (n - event[next].second);
else
dist2 = abs(event[p2].first - event[next].first) + abs(event[p2].second - event[next].second);
int res1 = dp[next][p2] + dist1;
int res2 = dp[p1][next] + dist2;
if (res1 < res2){
cout << 1 << "\n";
print_order(next, p2);
}
else{
cout << 2 << "\n";
print_order(p1, next);
}
}
int main(){
cin.tie(NULL);
cout.tie(NULL);
ios_base::sync_with_stdio(false);
//input
cin >> n >> w;
for(int i = 1; i <= w; i++)
cin >> event[i].first >> event[i].second;
memset(dp, -1, sizeof(dp));
//calculate min distance and output
cout << dfs(0, 0) << "\n";
print_order(0, 0);
}728x90
반응형
LIST
'Problem Solving > DP' 카테고리의 다른 글
| [백준(BOJ)] 카드 게임(11062번)_C++ (0) | 2023.09.06 |
|---|---|
| [백준(BOJ)] LCS(9251번)_C++ (0) | 2023.04.09 |
| [백준(BOJ)] ACM Craft(1005번)_C++ (0) | 2023.03.23 |
| [백준(BOJ)] 피보나치 함수(1003)_C++ (0) | 2023.03.22 |
| [백준(BOJ)] 행렬 곱셈 순서(11049번)_C++ (1) | 2023.03.21 |