트리에서의 다이나믹 프로그래밍은 보통 i번째 노드를 루트로 하는 서브트리
에서 i번째 루트노드를 포함했을때
와 포함 안했을때
중 최적값을 계산하는 방식이다.
DFS
를 사용하여 leaf node
의 값부터 알아내면서 문제를 해결하는 방식
기본적인 뼈대는 아래와 같다
visit
배열을 하나 만들고, 루트 노드로부터 자식 노드를 순차방문하면서 방문했으면 무시하고 방문을 안했을 때 dfs 재귀로 들어간다. 그렇게 leaf node
부터 값을 구하여 이를 이용해 root node
의 값을 구해간다.
package com;
import java.io.*;
import java.util.*;
public class Main {
static int n;
static boolean[] visit;
static LinkedList<Integer>[] tree;
static int[][] dp;
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(br.readLine());
dp = new int[n+1][2]; //0이면 얼리x, 1이면 얼리
visit = new boolean[n+1];
tree = new LinkedList[n+1];
for (int i = 1; i < n+1; i++) {
tree[i] = new LinkedList<>();
}
for (int i = 0; i < n-1; i++) {
StringTokenizer st = new StringTokenizer(br.readLine());
int u = Integer.parseInt(st.nextToken());
int v = Integer.parseInt(st.nextToken());
tree[u].add(v);
tree[v].add(u);
}
int root = 1;
dfs(root);
System.out.println(Math.min(dp[root][0], dp[root][1]));
}
private static void dfs(int root) {
visit[root] = true;
dp[root][0] = 0;
dp[root][1] = 1;
LinkedList<Integer> item = tree[root];
for(int child : item) {
if(!visit[child]) {
dfs(child);
dp[root][0] += dp[child][1];
dp[root][1] += Math.min(dp[child][0], dp[child][1]);
}
}
}
}
아직 트리에서의 DP는 감이 별로 안잡히니 여러 문제를 풀어봐야 할듯
코테에서도 비슷한 문제를 본적이 있다. 그때 문제랑 비슷했던 문제
https://www.acmicpc.net/problem/7812