🍑 OJ专栏
🍑 HDOJ 1562 The more, The Better
输入
3 2
0 1
0 2
0 3
7 4
2 2
0 1
0 4
2 1
7 1
7 6
2 2
0 0
输出
5
13
🙈 仿照大佬写的题解
🍑 AC
import java.util.*;
public class Main
{
static int N = 210;
static int[] v = new int[N];// 宝物数量(价值)数组
static int[][] f = new int[N][N];// 表示以 i 为根节点 选择 j 个城堡攻击的 最大宝物数量
// 邻接表存树
static ArrayList<Integer>[] list = new ArrayList[N];
public static void main(String[] args)
{
Scanner sc = new Scanner(System.in);
while (sc.hasNext())
{
// 多组测试数据,记得初始化
for (int i = 0; i < N; i++)
for (int j = 0; j < N; j++)
f[i][j] = 0;
for (int i = 0; i < N; i++)
list[i] = new ArrayList<Integer>();
int n = sc.nextInt();
int m = sc.nextInt();
if (n == 0 && m == 0)
break;
for (int i = 1; i <= n; i++)
{
int a = sc.nextInt();
v[i] = sc.nextInt();
f[i][1] = v[i];
// 第 i 个城堡依赖于 城堡a 即 a --> i
list[a].add(i);
}
dfs(0, m + 1);// 让 0 节点作为超级根节点
System.out.println(f[0][m + 1]);
}
}
private static void dfs(int x, int cnt)
{
int len = list[x].size();
for (int i = 0; i < len; i++)//遍历当前树的所有子树
{
int son = list[x].get(i);//某子树
if (cnt > 1)// 一进来,只要当前树还能分,那就向下 递归
dfs(son, cnt - 1);
for (int v = cnt; v >= 2; v--)//枚举分给子节点的所有可能
for (int j = 1; j < v; j++)// 根节点必须选,所以 j < v,留一个给根节点
f[x][v] = Math.max(f[x][v], f[x][v - j] + f[son][j]);
}
}
}