原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1011
题目名称:星舰部队
问题描述:
作为星河战队的领导者,你被派去摧毁这些虫子的基地。
基地为一个个房间连成的树形结构,每个房间都被一些虫子占据,里面也对应一定的大脑在房间里。
你必须在每个房间留下一些士兵来对抗里面的所有虫子。一个星舰士兵可以对抗20个虫子。
由于你没有足够的士兵,你只能清理一些房间,让神经气体完成其余的工作(无法获得大脑)。
计算最大所有可获得大脑的总和。
输入项:
输入包含多个测试用例。
从第一行开始,n m分别表示房间个数和士兵数。
接下来n行中每行为a b分别表示房间内的虫子数和大脑数
接下来的n-1行中每行为x y分别为表示房间连接情况,房间为树形连接,且无法退回
然后接着是下一个测试用例,直到-1 -1表示结束
输出项:
每一个测试用例可以捕获的大脑总数
解题技巧:
背包算法(参考ACM课本98页0-1背包),士兵是动态变多的,问题是从最后一个往上考虑的
测试用例:
5 10
50 10
40 10
40 20
65 30
70 30
1 2
2 4
1 3
2 5
1 1
20 7
-1 -1
输出结果:
50
7
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class Hdu1011 {
//每一次任务的前提所给信息
static ArrayList<Integer> roomsList[];//这是一个List的数组 每一个数组中存储
static int n, m;//n表示房间个数,m表示士兵个数
static int bugs_brains[][];//房间的虫子数和大脑的数量
static int dp[][];//dp[i][j]表示第i个洞消耗j个士兵的获得值
static boolean vis[];//标记本节点是否被遍历过
public static void main(String[] args) {
List<Hdu1011DataStructure> hdu1011DataStructureList = read();//读取输入的内容
for (Hdu1011DataStructure hdu1011DataStructure : hdu1011DataStructureList) {
System.out.println(count(hdu1011DataStructure));//对每次任务计算并输出最终结果
}
}
//单个准备工作
static int count(Hdu1011DataStructure hdu1011DataStructure) {
m = hdu1011DataStructure.getM();
if (m == 0) {//表示一开始就没有士兵
return 0;
}
n = hdu1011DataStructure.getN();
vis = new boolean[n + 1];//默认初始值为false
dp = new int[n + 1][m + 1];//初始值都为0
roomsList = hdu1011DataStructure.getRooms();
bugs_brains = hdu1011DataStructure.getBugs_brains();
//单个准备工作完毕
dfs_dp(1);//从1开始
return dp[1][m];
}
static void dfs_dp(int a) {//a表示节点编号
vis[a] = true;//标记本节点已经遍历了
int temp = (bugs_brains[a][0] + 19) / 20;//本节点需要的士兵
for (int i = temp; i <= m; i++)//在dp的第a行temp之后的内容都存放可以获得的大脑数量
dp[a][i] = bugs_brains[a][1];//dp表示第a个洞穴,消耗i个士兵获得的大脑,投入再多的士兵也只能获得这些大脑
for (int i = 0; i < roomsList[a].size(); i++) {//找到本节点所能到的节点
int to = roomsList[a].get(i);
if (vis[to] == true) continue;//如果已经弄完了,就不用弄了
dfs_dp(to);//处理下一个节点,到最后一次,dp中temp之后都存放了能获得的大脑数
for (int j = m; j >= temp; j--) {//j表示从temp到m所在的列数,重新修改a节点消耗temp个士兵所获得的大脑数,加上了子节点
for (int k = 1; k <= j - temp; k++)//
dp[a][j] = Math.max(dp[a][j], dp[a][j - k] + dp[to][k]);//da[a][j-k]从第1列到temp列,表示还没有被修改
}
}
}
static List<Hdu1011DataStructure> read() {
Scanner scanner = new Scanner(System.in);
String nm[] = scanner.nextLine().split(" ");
List<Hdu1011DataStructure> hdu1011DataStructureList = new ArrayList<>();
while (!nm[0].equals("-1")) {
int n = Integer.parseInt(nm[0]);
Hdu1011DataStructure h1011DataStructure = new Hdu1011DataStructure();
h1011DataStructure.setN(n);
h1011DataStructure.setM(Integer.parseInt(nm[1]));
//存放虫子数量和大脑数量n行
int bugs_brains[][] = new int[n + 1][2];
for (int i = 1; i < n + 1; ++i) {
String bug_brain[] = scanner.nextLine().split(" ");
bugs_brains[i][0] = Integer.parseInt(bug_brain[0]);
bugs_brains[i][1] = Integer.parseInt(bug_brain[1]);
}
h1011DataStructure.setBugs_brains(bugs_brains);//得到本次的大脑和虫子
//存放房间的情况n-1行
roomsList = new ArrayList[n + 1];//计数从1开始
for (int i = 0; i < roomsList.length; i++) {//初始化
roomsList[i] = new ArrayList<Integer>();
}
for (int i = 0; i < n - 1; i++) {
String room[] = scanner.nextLine().split(" ");
int a = Integer.parseInt(room[0]);
int b = Integer.parseInt(room[1]);
roomsList[a].add(b);
roomsList[b].add(a);
}
h1011DataStructure.setRooms(roomsList);//得到本次的房间关系
hdu1011DataStructureList.add(h1011DataStructure);
nm = scanner.nextLine().split(" ");
}
return hdu1011DataStructureList;
}
}
对应数据结构(Java对象):
import java.util.ArrayList;
import java.util.Arrays;
public class Hdu1011DataStructure {
private int n, m;//n表示房间个数,m表示士兵数量
private int bugs_brains[][];//i 0表示虫子数,i 1表示大脑数量
private ArrayList<Integer> rooms[];//数组i=1中的列表中的内容为1所能到的节点
@Override
public String toString() {
return "Hdu1011DataStructure{" +
"n=" + n +
", m=" + m +
", bugs_brains=" + Arrays.toString(bugs_brains) +
", rooms=" + rooms +
'}';
}
public ArrayList<Integer>[] getRooms() {
return rooms;
}
public void setRooms(ArrayList<Integer>[] rooms) {
this.rooms = rooms;
}
public int getN() {
return n;
}
public void setN(int n) {
this.n = n;
}
public int getM() {
return m;
}
public void setM(int m) {
this.m = m;
}
public int[][] getBugs_brains() {
return bugs_brains;
}
public void setBugs_brains(int[][] bugs_brains) {
this.bugs_brains = bugs_brains;
}
}