https://www.acmicpc.net/problem/12978

 

12978번: 스크루지 민호 2

구두쇠로 유명한 스크루지 민호가 다스리는 천나라가 있다. 천나라에는 N 개의 도시들이 있는데 각각의 도시들 사이에는 양방향 도로로 이어져 있다. 민호는 도시를 세울 때 최소한의 비용만을

www.acmicpc.net

오랜만에 알고리즘 포스팅입니다.

 

N개의 도시와 N - 1개의 도로인 것으로 보아 트리 문제인 것으로 파악할 수 있으며,

최소 갯수의 경찰서를 세워 모든 도시, 도로를 감시해야 합니다.

 

모든 도시들 대상으로 경찰서를 세우는 경우, 세우지 않는 경우를 모두 구한다면 시간초과가 발생할 것입니다.

따라서 dp를 추가하여 treedp로 접근합니다.

 

dp[v][flag]: 현재 도시가 v이고, 상태가 flag일 때 세워야할 경찰서의 최소 갯수

여기서 상태란, 현재 도시에 경찰서를 세울지 결정하는 변수입니다.

flag = 1 일 때, 해당 도시에 경찰서를 세우고,

flag = 0 일 때, 해당 도시에 경찰서를 세우지 않는 경우입니다.

 

이러면 다음 도시부터는 계산하기 수월해집니다.

현재 도시에서 경찰서를 세웠더라면 다음 도시에서는 경찰서를 세워도 되고, 세우지 않아도 됩니다. 즉, 두 경우 모두 확인합니다.

현재 도시에서 경찰서를 세우지 않았더라면 다음 도시에서는 경찰서를 무조건 세워야 합니다. 즉, 하나의 경우만 확인합니다.

마지막으로 해당 경우의 합의 최솟값을 출력합니다.

 

 

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include <iostream>
#include <algorithm>
#include <vector>
#include <cstring>
#define MAX 100001
using namespace std;
 
vector<int> graph[MAX];
int dp[MAX][2];
int N;
 
int dfs(int v, int pre, int flag) {
    int& ret = dp[v][flag];
    if (ret != -1return ret;
    ret = flag;
 
    for (auto next : graph[v]) {
        if (pre == next) continue;
        if (flag) {
            ret += min(dfs(next, v, 1), dfs(next, v, 0));
        }
        else {
            ret += dfs(next, v, 1);
        }
    }
 
    return ret;
}
 
void func() {
    memset(dp, -1sizeof(dp));
    cout << min(dfs(101), dfs(100)) << '\n';
}
 
void input() {
    int u, v;
    cin >> N;
    for (int i = 0; i < N - 1; i++) {
        cin >> u >> v;
        graph[u].push_back(v);
        graph[v].push_back(u);
    }
}
 
int main() {
    cin.tie(NULL); cout.tie(NULL);
    ios::sync_with_stdio(false);
 
    input();
    func();
 
    return 0;
}
cs

'algorithm > dp' 카테고리의 다른 글

boj 2015 수들의 합 4  (0) 2022.08.12
boj 21923 곡예 비행  (0) 2022.06.10
boj 10986 나머지 합  (0) 2022.03.08
boj 14238 출근 기록  (0) 2022.02.04
boj 3673 나눌 수 있는 부분 수열  (0) 2022.01.31

+ Recent posts