🍑 OJ专栏
🍑 HDOJ 1011 Starship Troopers
输入
5 10
50 10
40 10
40 20
65 30
70 30
1 2
1 3
2 4
2 5
1 1
20 7
-1 -1
输出
50
7
🙈 模仿大佬题解
🍑 AC
import java.util.*;
public class Main
{
static List<Integer>[] vec;// 邻接表存树
static int n, m;
static int[] bug;// 存 需要 多少个士兵才能解决里边的虫子
static int[] pro;// 存首脑出现的可能性
static boolean[] st;// 去重数组
static int[][] f;
public static void main(String[] args)
{
Scanner sc = new Scanner(System.in);
while (sc.hasNext())
{
n = sc.nextInt();
m = sc.nextInt();
if (n == -1 && m == -1)
{
break;
}
bug = new int[n + 1];
pro = new int[n + 1];
st = new boolean[n + 1];
f = new int[n + 1][m + 1];
vec = new ArrayList[n + 2];
for (int i = 0; i <= n; i++)
{
vec[i] = new ArrayList<>();// 初始化 邻接表数组
}
for (int i = 1; i <= n; i++)
{
int a = sc.nextInt();
pro[i] = sc.nextInt();
bug[i] = (a % 20 == 0 ? a / 20 : a / 20 + 1);// 向上取整((a+19)%20 也行)
// 初始化:枚举需要的士兵数,只要达到指定的数量,往上都可以拿下
for (int j = bug[i]; j <= m; j++)
{
f[i][j] = pro[i];
}
}
for (int i = 1; i <= n - 1; i++)
{
int a = sc.nextInt();
int b = sc.nextInt();
vec[a].add(b);
vec[b].add(a);
}
if (m == 0)// 特判掉特殊案例
{
System.out.println("0");
continue;
}
dfs(1, m);
System.out.println(f[1][m]);
}
}
// s表示当前士兵数量
public static void dfs(int x, int s)
{
st[x] = true;
for (int i = 0; i < vec[x].size(); i++)
{
int y = vec[x].get(i);
if (!st[y])// 不走回头路
{
if (s > bug[x])
{
dfs(y, s - bug[x]);
}
// j 必须得同时大于自己的和子节点的bug值才能继续分下去
for (int j = s; j >= bug[x] + bug[y]; j--)
{
// 必须保证根节点 x 已经被消灭了,即消耗了bug[x]的兵力
for (int k = 1; k <= j - bug[x]; k++)
{
// 节点 x 还剩j-k兵力,y 派遣 k 的兵力
f[x][j] = Math.max(f[x][j], f[x][j - k] + f[y][k]);
}
}
}
}
}
}