Life: research & education/PS
백준 2618번 경찰차 (boj/2618.c)
KMS studio
2024. 1. 14. 13:42
DP문제입니다. 공간복잡도 O(W^2), 시간복잡도 O(W^2)으로 해결가능합니다.
또한 각 사건마다 할당된 경찰관을 묻고 있기 때문에 간단한 자취 남기기 기법을 응용합니다.
DP의 구성은 아래와 같습니다.
회색 영역은 초기화 때 계산됩니다.
빗금 영역에 있는 값 중 최소의 값을 문제의 답으로 결정합니다.
한 번에 계산되는 양은 아래와 같습니다.
코드는 아래와 같습니다.
#include <stdio.h>
#include <math.h>
#define SZE 1000
int dp[SZE+1][SZE+1];
int idx[SZE+1][2];
int giv[SZE+1] = { 0, };
typedef struct _p{
int row;
int col;
}point;
point loc[SZE+1];
int get_dst(point p1, point p2){
return abs(p1.row-p2.row) + abs(p1.col-p2.col);
}
int main(void){
int N, W;
int row, col, tmp;
int cur_row, cur_col, rec;
int res;
point pol1, pol2;
scanf("%d %d", &N, &W);
pol1.row=pol1.col=1; pol2.row=pol2.col=N;
for(int i=1;i<=W;i++){
scanf("%d %d", &row, &col);
loc[i].row=row; loc[i].col=col;
}
//gray area (tmp = length loc1 to loci)
tmp = 0;
for(int i=1;i<=W;i++){
if(i>1){ tmp += get_dst(loc[i-1], loc[i]); }
dp[0][0] = 0;
dp[i][0] = get_dst(pol1, loc[1]) + tmp;
dp[0][i] = get_dst(pol2, loc[1]) + tmp;
}
for(int i=1;i<W;i++){
//black area
dp[i][i]=-1;
//dark green area
dp[i][i+1] = dp[i][0] + get_dst(pol2, loc[i+1]); idx[i][1] = 0;
for(int j=1;j<i;j++){
tmp = dp[i][j] + get_dst(loc[j], loc[i+1]);
if(tmp < dp[i][i+1]){ dp[i][i+1] = tmp; idx[i][1]=j; }
}
//dark red area
for(int j=i+2;j<=W;j++){ dp[i][j] = dp[i][j-1] + get_dst(loc[j-1], loc[j]); }
//light green area
dp[i+1][i] = dp[0][i] + get_dst(pol1, loc[i+1]); idx[i+1][0] = 0;
for(int j=1;j<i;j++){
tmp = dp[j][i] + get_dst(loc[j], loc[i+1]);
if(tmp < dp[i+1][i]){ dp[i+1][i]=tmp; idx[i+1][0]=j; }
}
//light red area
for(int j=i+2;j<=W;j++){ dp[j][i] = dp[j-1][i] + get_dst(loc[j-1], loc[j]); }
}
//search answer
res = dp[0][W];
for(int i=0;i<W;i++){
if(res > dp[i][W]){
res = dp[i][W];
cur_row=i; cur_col=W; }
if(res > dp[W][i]){
res = dp[W][i];
cur_row=W; cur_col=i; }
}
//make path
rec=W;
while(rec--){
if(cur_row > cur_col+1){
giv[rec] = 1; cur_row--; }
else if(cur_row == cur_col+1){
giv[rec] = 1; cur_row=idx[cur_row][0]; }
else if(cur_row+1 == cur_col){
giv[rec] = 2; cur_col=idx[cur_row][1]; }
else if(cur_row+1 < cur_col){
giv[rec] = 2; cur_col--; }
else{ giv[rec]=-1; }
}
printf("%d\n", res);
for(int i=0;i<W;i++){ printf("%d\n", giv[i]); }
return 0;
}