HDU 1011 Starship Troopers
题目
http://acm.hdu.edu.cn/showproblem.php?pid=1011
作为星河战队的领导者,你被派去摧毁这些虫子的基地。
基地为一个个房间连成的树形结构,每个房间都被一些虫子占据,对应一定的大脑(分数)在房间里。为了尽快完成战斗,你不想等到部队人员清理房间后再前进到下一个房间,而是你必须在每个房间留下一些士兵来对抗里面的所有虫子。一个星舰士兵可以对抗20个虫子。由于你没有足够的士兵,你只能占用一些房间,让神经气体完成其余的工作(无法获得大脑)。计算最大所有可获得大脑的总和。
输入输出
输入:
N(房间个数)M(士兵个数)
N行,每行两个数,bugs[i](房间虫子数目)brain(房间大脑数目)
N-1行,每行两个数,room1 room2(room1和room2相连)
多组数据,-1,-1结束
输出:
最大获得大脑总和
多组数据
思路
dp[i][j]:第i个节点用去j个士兵获得的最大大脑数目
状态转移公式:dp[node][j]=max(dp[node][j],dp[node_son][l]+dp[node][j-l]);
树形DP:dfs
坑~
1.士兵个数M=0时,即使bugs=0,brains!=0,结果仍未0。
2.即使bugs=0不需要士兵消灭虫子也需要有士兵走过改路线。可设置叶子结点bugs=0为bugs=1。
3.两个房间连接的输入不一定是从父节点到子节点的,即需要存入无向图然后设置标志位实现树形的遍历。
4.见题目注释。
#pragma comment(linker,"/STACK:102400000,102400000")
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<iomanip>
#include<algorithm>
#include<numeric>
#include<functional>
#include<memory>
#include<cmath>
#include<cstring>
#include<string>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<vector>
#include<fstream>
#define min(a,b) (a)<(b)?(a):(b)
#define max(a,b) (a)>(b)?(a):(b)
#define lc(x) (x<<1)
#define rc(x) (x<<1|1)
const double pi=acos(-1.0);
const int INF=0x3f3f3f3f;
const int MAX=0x7fffffff;
const long long LINF=0x3f3f3f3f3f3f3f3f;
const long long LMAX=0x7fffffffffffffff;
const double eps=1e-9;
const int Mod=100007;
const int Max=10000005;
using namespace std;
int N,M;
int bugs[102],brains[102];
int a[102][102];
int dp[102][102];
bool f[102];
vector<int> v[102];
void dfs(int node){
f[node]=1;
int node_min;
node_min=(bugs[node]+19)/20;
for(int i=node_min;i<=M;++i){
dp[node][i]=brains[node];
}
int son_nums,node_son,node_son_min;
son_nums=v[node].size();
for(int i=0;i<son_nums;++i){
node_son=v[node][i];
if(f[node_son]==0)
{
dfs(node_son);
//for(int j=node_min;j<=M;++j){//不能从小到大,以为j大值有小值更新
for(int j=M;j>=node_min;--j){
//node_son_min=(bugs[node_son]+19)/20;
//for(int l=node_son_min;j-l>=node_min;++l){//需要从1开始,以为node节点可以不取
for(int l=1;j-l>=node_min;++l){
dp[node][j]=max(dp[node][j],dp[node_son][l]+dp[node][j-l]);
}
}
}
}
}
int main() {
freopen("data.in","r",stdin);
cin.sync_with_stdio(false);
cout.sync_with_stdio(false);
while((cin>>N>>M)&&N!=-1&&M!=-1){
for(int i=1;i<=N;++i){//init
v[i].clear();
}
memset(dp,0,sizeof(dp));
memset(f,0,sizeof(f));
for(int i=1;i<=N;++i){//read
cin>>bugs[i]>>brains[i];
}
int room1,room2;
for(int i=0;i<N-1;++i){
cin>>room1>>room2;
v[room1].push_back(room2);
v[room2].push_back(room1);
}
for(int i=1;i<=N;++i){//
if(v[i].size()==1&&i!=1&&bugs[i]==0){//树形结构只有1--2时,1的size也是1
bugs[i]=1;
}
}
if(M==0){//doit
cout<<0<<endl;
}else{
dfs(1);
cout<<dp[1][M]<<endl;
}
}
fclose(stdin);
return 0;
}