HDOJ 1011 Starship Troopers 树形DP 依赖背包

🍑 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]);
					}
				}
			}
		}
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值