Problem Solving/Else
BOJ 1949 : 우수 마을
PS리버싱마크해커박종휘TV
2022. 4. 3. 17:57
3줄요약
- 트리
- DP
문제풀이 |
우리는 문제에서 주어진 3가지 조건들을 만족해나가면서 풀어야 한다.
여기서 우리가 주목해야 할 점은 3번 조건이다. 우리는 약간 생각해보면 3번 조건이 1, 2번 조건에 통합된다는 것을 알 수 있다. 애초에 인접한 마을이 모두 우수 마을이 아니면, 2번 조건이 성립하지 않으므로 그냥 그 마을을 우수 마을로 선정하는 것이 더 이득일 수 있다. 즉, 3번 조건을 만족하지 않는 해가 있다면 그것은 최적의 해가 아니라는 소리다.
이제 진짜 문제풀이로 가보도록 하자.
dp[node][a] 를 정의한다. (a = 이 마을을 우수 마을로 설정할 것이면 1, 아니면 0)
Top-Down 방식(dfs)로 해결한다:
만약 a가 1이라면, dp[nxt][0] 을 dp[node][a] 에 더한다. (nxt는 다음 노드) 2번 조건이 있기 떄문에 이렇게 한다.
아니라면, max(dp[nxt][0], dp[nxt][1])를 dp[node][a] 에 더한다.
코드는 밑에 있다.
#include <iostream>
#include <vector>
using namespace std;
int N;
vector<int> tree[10001];
int vils[10001];
int dp[10001][2];
int dfs(int node, int yes, int old) { // yes = 현재 마을을 우수 마을로 선정했을 경우
int& cache = dp[node][yes];
if (cache) return cache;
for (int i = 0; i < tree[node].size(); i++) {
int nxt = tree[node][i];
if (nxt == old) continue;
if (yes) cache += dfs(nxt, 0, node); // 2번 조건
else cache += max(dfs(nxt, 0, node), dfs(nxt, 1, node));
/*
3번 조건은 신경쓸 필요 없음:
어짜피 밑에꺼가 이득이면 자동으로 인접하게 되어 있음
*/
}
if (yes) cache += vils[node];
return cache;
}
int main() {
cin >> N;
for (int i = 1; i <= N; i++) {
cin >> vils[i];
}
for (int i = 0; i < N - 1; i++) {
int from, to; cin >> from >> to;
tree[from].push_back(to);
tree[to].push_back(from);
}
cout << max(dfs(1, 1, 1), dfs(1, 0, 1)) << endl;
}
난이도(개인적): Gold II
난이도(객관적): Gold II