레야몬
[C++] 1949번 우수 마을 - DP, 트리, 트리에서의 DP 본문
1. 문제
- N개의 마을로 이루어진 나라가 있다. 마을에는 1~N까지의 번호가 붙어있다. 이 나라는 트리 구조이며 무방향성이다. N개의 마을 중 몇 개의 마을을 '우수 마을'로 설정하려고 한다.
- '우수 마을'로 선정된 마을 주민 수의 총합을 최대로 한다.
- '우수 마을'끼리는 서로 인접할 수가 없다.
- ;우수 마을'로 선정되지 못한 마을은 적어도 하나의 '우수 마을'과 인접하여야 한다.
<입력>
- - 1 - \(N(1 \leq N \leq 10,000)\)
- - 2 - 마을 주민 수 \(popu(0 \leq popu \leq 10,000)\)
- - M-1개줄 - 인접한 두 마을의 번호
<출력>
- '우수 마을'의 주민 수 총합
2. 재정의
- 트리에서 최대, 인접 X, 반드시 우수가 아닌 마을은 우수와 인접. 이때 최댓값은?
3. 해결 방법
- dp[no][0] = max(dp[next][1], dp[next][0])
- dp[no][1] = dp[next][1] + popu[no]
- dp[no][0]에서 다음다음 자식 노드가 0이면 no의 다음 자식 노드가 1이 안됨에도 불구하고 max라는 함수에 의해 그리디적인 방법으로 항상 이 경우가 제외되므로 위와 같이 풀 수 있다. (뭔 말인지 모르겠지??ㅋㅋㅋㅋ)
4. 실수한 점, 개선할 점
- 위에 정당성을 증명한다고 꾀나 애먹었다. 애초에 잠도 오는 상황이었으니 뭐.... 실제로 푼 시간을 합치면 한 25분 정도로 아이디어 내고 코딩 시작한 듯.
<코드>
#include <iostream>
#include <vector>
using namespace std;
const int MAX_N = 10001;
// <문제>
// 마을의 개수 N
int N;
// 마을의 주민 수 popu[]
int popu[MAX_N];
// 트리
vector<int> adj[MAX_N];
// DFS용 방문한 노드 메모 vi
int vi[MAX_N];
// dp
int dp[MAX_N][2];
void input() {
cin >> N;
for(int i=1; i<=N; i++)
cin >> popu[i];
for(int i=0; i<N-1; i++) {
int u, v;
cin >> u >> v;
adj[u].push_back(v);
adj[v].push_back(u);
}
}
void DFS(int no) {
vi[no] = 1;
for(auto next : adj[no]) {
// 아직 방문하지 못한 곳
if(!vi[next]) {
DFS(next);
// 우수 마을이 아닌 경우
dp[no][0] += max(dp[next][1], dp[next][0]);
// 우수 마을인 경우
dp[no][1] += dp[next][0];
}
}
dp[no][1] += popu[no];
}
int main() {
ios_base::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
input();
DFS(1);
cout << max(dp[1][0], dp[1][1]);
return 0;
}
<문제 바로가기>
https://www.acmicpc.net/problem/1949
1949번: 우수 마을
N개의 마을로 이루어진 나라가 있다. 편의상 마을에는 1부터 N까지 번호가 붙어 있다고 하자. 이 나라는 트리(Tree) 구조로 이루어져 있다. 즉 마을과 마을 사이를 직접 잇는 N-1개의 길이 있으며,
www.acmicpc.net
※현재 고등학교 등교 중인 학생입니다. 이제 알고리즘을 본격적으로 공부하기 시작해서 아직 초보입니다. 혹시 제가 잘못 알고 있는 점이나 더 좋은 풀이 방법이 있어 댓글에 남겨주시면 감사히 하나하나 열심히 읽어보겠습니다. 좋아요, 단순한 댓글 한마디라도 저에겐 큰 힘이 됩니다! 감사합니다.
'알고리즘 > 백준' 카테고리의 다른 글
[C++] 20149번 선분 교차 3 - 기하학, 많은 조건 분기, 선분 교차 판정 (0) | 2022.12.13 |
---|---|
[C++] 2213번 트리의 독립집합 - DP, 트리, 트리에서 DP (0) | 2022.12.13 |
[C++] 4386번 별자리 만들기 - 그래프 이론, 최소 스패닝 트리 (0) | 2022.12.12 |
[C++] 4195번 친구 네트워크 - 자료 구조, 해시를 사용한 집합과 맵, 분리 집합 (0) | 2022.12.12 |
[C++] 1717번 집합의 표현 - 자료 구조, 분리 집합 (0) | 2022.12.12 |
Comments