您的位置:首页 > 运维架构

hdu 1011 Starship Troopers 树形dp

2012-10-03 15:56 567 查看
hdu 1011 Starship Troopers

http://acm.hdu.edu.cn/showproblem.php?pid=1011

题意: 一个洞穴有很多房间,每个房间有一些bug和brain,拥有一些Troopers可以消灭bug,一个Troopers可以消灭20个bug,Troopers已走过 的房间不可以再回去,同时留下消灭bug的Troopers不可以再去其他房间消灭bug,问最多可以得到多少brain

注意几点:

1 建图时建无向图,题中给定的点不一定先给的就是父节点,所以用一个vis记录是否走过

2 即使bug数为0,要取得此节点的bug也至少要有一个Troopers走过,但不一定留下

状态转移方程:dp[p][j] = MAX( dp[p][j], dp[p][j-k] + dp[tmp][k]);

dp[p][j] 表示p点用j个人攻打所得收益

之后就是背包思想了

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int maxn = 110;
struct node{
int v, next;
}edge[2*maxn];
struct CC{
int bug, w;
}cav[maxn];
int pre[maxn], value, m, n, dp[maxn][maxn], vis[maxn];
int MAX(int x, int y){
return x>y? x:y;
}
void init(){
int i, j, k, aa, bb;
memset( pre, -1, sizeof( pre));
value = 0;
for( i= 1; i<= n; i++){
scanf("%d%d", &cav[i].bug, &cav[i].w);
cav[i].bug = (cav[i].bug + 19)/20;
}
for( i= 1; i<n; i++){
scanf("%d%d", &aa, &bb);
edge[value].v = bb;
edge[value].next = pre[aa];
pre[aa] = value++;
edge[value].v = aa;
edge[value].next = pre[bb];
pre[bb] = value ++;
}
}
void dfs( int p){
int i, j, k, tmp;
vis[p] = 1;
for( i= cav[p].bug; i<= m; i++){
dp[p][i] = cav[p].w;
}
for( i= pre[p]; i!= -1; i= edge[i].next){
tmp = edge[i].v;
if( vis[tmp]) continue;
dfs(tmp);
for( j= m; j>= cav[p].bug; j--){ // 0 1 背包 dp[p][j] 不受 dp[p][j-1]影响
for( k = 1; k<= j- cav[p].bug; k++){ //完全背包
dp[p][j] = MAX( dp[p][j], dp[p][j-k] + dp[tmp][k]);
}
}
}
}
int main(){
//freopen("1.txt", "r", stdin);
int mm, i;
while( scanf("%d%d", &n, &m) && !( m == -1 && n== -1)){
init();
if( m == 0) {
printf("0\n");
continue;
}
memset( vis, 0, sizeof( vis));
memset( dp, 0, sizeof( dp));
dfs(1);
printf("%d\n", dp[1][m]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: