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

HDU 1011 Starship Troopers 树形DP(0-1背包)

2012-08-14 15:06 471 查看
题意:一棵树,有n个结点,每个结点有w[i]个bug,有p[i]的brain。我从1号结点开始走,带着m个战士。
1个战士可以消灭20个bugs如果我把某个结点的所有bug都消灭了我就能得到那个结点的brain。
如果想攻击当前结点,那么必须先攻击了它的父结点(1号点除外)。
注意:
1. 其中当你攻占了当前结点,你可以分派人手,走向几个不同的子结点,去攻占更多。也就是说,不是单一的路径。

2. 如果输入0个战士直接输出0,即使该洞bug数为0,要获得该洞brain值,也需要至少一人经过该洞穴(可以不停留),而用dfs计算会出现正值。

本题数据小,节点100,如果数据大了尽量不要用vector,可能会超时,建议自己写个邻接表。

树形DP,有一定的格式,下面是最常见的模板(一般题目都可以这么做):

void dfs(int u)
{
int i, j, k;
vis[u]=1;
操作:u节点dp初始化
for(i=0;i<edge[u].size();i++)
{
int v=edge[u][i];
if(vis[v])continue;
dfs(v);
操作:子节点状态转移到父亲节点
}
}

int main()

{

操作:输入

操作:建图

dfs(根节点);

printf("根节点的状态");

}


AC代码:

View Code

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<vector>
using namespace std;
int n, m, w[101], p[101];
bool vis[101];
vector<int>edge[101];
int dp[101][101];
void dfs(int u)
{
int i, j, k;
vis[u]=1;
//for(j=0;j<w[u];j++)//各节点初始化,如果能装,先把节点u的物品装进背包
//    dp[u][j]=0;
for(j=w[u];j<=m;j++)
dp[u][j]=p[u];
for(i=0;i<edge[u].size();i++)
{
int v=edge[u][i];
if(vis[v])continue;
dfs(v);
for(j=m;j>=w[u];j--)
for(k=1;k<=j&&j-k>=w[u];k++)
dp[u][j]=max(dp[u][j],dp[u][j-k]+dp[v][k]);
}
}
int main()
{
int i ,j, x, y;
while(~scanf("%d%d",&n,&m))
{
if(m==-1&&n==-1)break;
for(i=1;i<=n;i++)
edge[i].clear();
for(i=1;i<=n;i++)
scanf("%d%d",&w[i],&p[i]),w[i]=(w[i]+19)/20;
for(i=1;i<n;i++)
{
scanf("%d%d",&x,&y);
edge[x].push_back(y);
edge[y].push_back(x);
}
memset(dp,0,sizeof(dp));
memset(vis,0,sizeof(vis));
//即使该洞bug数为0,要获得该洞brain值,也需要至少一人经过该洞穴(可以不停留)。
if(!m){printf("0\n");continue;}//必须要考虑0这个特殊数据。
dfs(1);
printf("%d\n",dp[1][m]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: