您的位置:首页 > 大数据 > 人工智能

HDU 4340 Capturing a country 2012 Multi-University Training Contest 5

2013-07-24 21:49 330 查看
纪念一下九野先森终于摆脱苦逼的VC++6.0,改换2012的1A水题

给定N,M 代表N个点 M个士兵,The following N lines indicate 攻占该点需要的士兵数(1个士兵能扣它20血。。)还有打败后能获得的brain值,next following N-1 lines indicate 点的连通(是无向边) 也就是一棵树

从1开始进攻,(1是根节点)想要攻打子节点必须先占领父节点

求最大的brain值

代码

#include<stdio.h>
#include <iostream>
#include <string.h>
using namespace std;
#define N 105
#define INF 1<<30
int w
,v
,dp

;//dp[i][j] 代表i点使用了j个士兵时最大的brain值
int G

,n,m;
bool vis
;
inline int Max(int a,int b){return a<b?b:a;}
void addedge(int u,int v){G[u][++G[u][0]]=v;}//vector的动态数组会方便看 这里G[u][0]是u点的度

void dfs(int u)
{
	vis[u]=true;
	int i;
	for(i=w[u];i<=m;i++) dp[u][i]=v[u];//单单对于u点,i个士兵的最大brain
	for(i=1;i<=G[u][0];i++)
	{
		int v=G[u][i];
		if(vis[v])continue;
		dfs(v);//这里是 树形dp 的重要代码,首先是遍历所有子节点再背父节点
		for(int j=m;j>=w[u];j--)//标准的背包
		{
			for(int k=1;k<=j-w[u];k++)
				dp[u][j]=Max(dp[u][j],dp[u][j-k]+dp[v][k]);//u点用了j个士兵能得到的最大brain
		}
	}
}
int main(){
	while (cin>>n>>m,n!=-1)
	{
		int i;
		for(i=1;i<=n;i++)
		{
			int use;	cin>>use>>v[i];
			w[i]=(use+19)/20;	
		}
		memset(G,0,sizeof(G));
		for(i=1;i<n;i++)
		{
			int u,v;	cin>>u>>v;
			addedge(u,v); addedge(v,u);
		}
		if(!m)cout<<"0"<<endl;
		else
		{
			memset(vis,0,sizeof(vis));
			memset(dp,0,sizeof(dp));
			dfs(1);
			cout<<dp[1][m]<<endl;
		}
	}
	return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐