POJ-1155 TELE (树形DP+分组背包)

题目大意:给一棵带边权的有根树,每个叶子节点有权。边权表示代价,叶子节点的权值代表可以补偿多少代价。问从根节点最多可以到达多少个叶子,使得付出的总代价不大于0。

题目分析:定义状态dp(u,k)表示从u开始到达k个叶子所花费的最小代价。则状态转移方程为:

dp(u,k)=min(dp(u,k),dp(son,j)+dp(u,k-j)+u到son的代价)。

ps:要加上优化,否则超时。

代码如下:

# include<iostream>
# include<cstdio>
# include<cstring>
# include<algorithm>
using namespace std;

const int N=3005;
const int INF=1000000000;

struct Edge
{
	int to,w,nxt;
};
Edge e[N];
int n,m,cnt;
int w[N];
int head[N];
int dp[N][N];

void add(int u,int v,int w)
{
	e[cnt].to=v;
	e[cnt].w=w;
	e[cnt].nxt=head[u];
	head[u]=cnt++;
}

void init()
{
	int k,a,b;
	cnt=0;
	memset(head,-1,sizeof(head));
	for(int i=1;i<=n-m;++i){
		scanf("%d",&k);
		while(k--)
		{
			scanf("%d%d",&a,&b);
			add(i,a,b);
		}
	}
	for(int i=n-m+1;i<=n;++i)
		scanf("%d",w+i-n+m-1);
}

int dfs(int u)
{
	for(int i=0;i<=m;++i)
		dp[u][i]=INF;
	dp[u][0]=0;
	if(u>n-m){
		dp[u][1]=-w[u-n+m-1];
		return 1;
	}
	int tot=0;
	for(int i=head[u];i!=-1;i=e[i].nxt){
		int v=e[i].to;
		tot+=dfs(v);
		for(int j=tot;j>=1;--j)
			for(int k=0;k<=j;++k)
				dp[u][j]=min(dp[u][j],e[i].w+dp[v][k]+dp[u][j-k]);
	}
	return tot;
}

void solve()
{
	dfs(1);
	int ans=0;
	for(int i=m;i>=0;--i){
		if(dp[1][i]<=0){
			ans=i;
			break;
		}
	}
	printf("%d\n",ans);
}

int main()
{
	while(~scanf("%d%d",&n,&m))
	{
		init();
		solve();
	}
	return 0;
}

  

时间: 2024-10-13 14:10:49

POJ-1155 TELE (树形DP+分组背包)的相关文章

[POJ 1155] TELE (树形dp)

题目链接:http://poj.org/problem?id=1155 题目大意:电视台要广播电视节目,要经过中转机构,到观众.从电视台到中转商到观众是一个树形结构,经过一条边需要支付成本.现在给你每两个节点之间传播的成本,给你每个观众会付的钱,问你电视台在不亏本的情况下最多能给多少个观众看节目. 这是我的第一道树形dp..无耻的看了题解.. 设计状态:dp[u][i]代表以u为根的子树中有i个观众,能够得到的最大收入. 状态转移:dp[u][i] = max(dp[u][i],dp[u][i-

POJ 1155 TELE 树形背包问题

题目描述看的莫名其妙,很久才看懂. 就是很裸的树形背包问题吧,状态是dp(i,j)表示节点i取到j个客户能得到的最大收益. 注意一开始初始化的时候所有j为0的时候应该是0,然后其他值都要初始化成负无穷,因为收益有可能是负值. 然后做01背包的时候注意方向,防止出现取某一个元素多次 #include <cstdio> #include <cstring> #include <iostream> #include <map> #include <set&g

hdu4003 树形dp+分组背包

http://acm.hdu.edu.cn/showproblem.php?pid=4003 Problem Description Humans have discovered a kind of new metal mineral on Mars which are distributed in point‐like with paths connecting each of them which formed a tree. Now Humans launches k robots on

HDU ACM 4044 GeoDefense -&gt;树形DP+分组背包

题意:地图是一个编号为1-n的节点的树,节点1是敌方基地,其他叶节点是我方基地.敌人基地会出来敌人,为了防止敌人攻进我方基地,我们可以选择造塔.每个节点只能造一个塔,节点i有ki种塔供选择,价值和攻击力为price_i, power_i,攻击力power_i是让敌人经过这个节点时让敌人的HP减少power_i点.因此从敌人基地到我方任意一个基地的路径,这条路径上所有塔的攻击力之和,就是这个基地的抵抗力. 敌人攻击路径不确定,为了保护我方所有基地,需要确定所有基地中抵抗力最低的一个.我方只有数量为

[P1273] 有线电视网 (树形DP+分组背包)

题意:给出一棵树,有边权,只有叶子节点有点权,求一个合法方案(选择走到哪几个叶子节点,且路径上的权值和 <= 要走到的叶子节点的点权和),使得选择的叶子节点数量尽量的多: 解法:树形DP+分组背包: 1.树形DP:这是一棵树,所以叫树形DP: 2.分组背包:在这里主要是运用到了它的思想:我们可以设 f[i][j],表示 i节点选择了 j个叶子节点的费用最大值:假设现在在 x节点,它的下面有 n个叶子节点(不是它的儿子),那么我们就要处理出它选 1,2,3,……,n 个叶子节点的情况,但是由于这是

poj 1155 TELE(树形泛化背包dp)

/* 这道题还不错,自己想出了思路过得也比较快,也得出了一个小经验,以后写这种题先把关键部分伪代码写出来这样会快很多而且 不那么容易出错,省去很多的调试时间 这道题就是转化为一道树形背包问题.首先把需要付的钱转为负数,对每个叶子结点增加一个子节点表示赚的钱,为正数. 然后记录下当前结点的所有可能的用户数目所花费的钱.所以问题就转化为一道简单的树形dp问题.最后找出盈利为非负数的最大 用户数即可. 有一点要注意dp数组初始化为一个很大的负数,刚开始因为这个问题wa了一遍 用到了num数组存放每个结

POJ 2486 Apple Tree 树形DP+分组背包

链接:http://poj.org/problem?id=2486 题意:一棵(苹果)树,树上有N个结点(N<=100),起点是结点1.每个结点上有若干个苹果,我可以进行K步操作(K<=200),每次操作是从当前结点移动到相邻的结点,并且到了相邻的结点以后会吃掉上面的所有苹果并且苹果不再长出来,相邻是指两个结点之间有边相连.问在K步操作之后最多可以吃掉多少个苹果. 思路:刚入手的时候觉得是一般的树形背包问题,dp[i][j]代表的是以i为根的子树中走j个结点所能吃到的苹果数,来进行状态转移,但

hdu4044 树形dp+分组背包

http://acm.hdu.edu.cn/showproblem.php?pid=4044 Problem Description Tower defense is a kind of real-time strategy computer games. The goal of tower defense games is to try to stop enemies from reaching your bases by building towers which shoot at them

HDU-1011 Starship Troopers (树形DP+分组背包)

题目大意:给一棵有根带点权树,并且给出容量.求在不超过容量下的最大权值.前提是选完父节点才能选子节点. 题目分析:树上的分组背包. ps:特判m为0时的情况. 代码如下: # include<iostream> # include<cstdio> # include<vector> # include<cstring> # include<algorithm> using namespace std; const int N=105; const

hdu 1561 树形dp+分组背包

题意:就是给定n个点,每个地点有value[i]的宝物,而且有的宝物必须是另一个宝物取了才能取,问取m个点可以获得的最多宝物价值. 一个子节点就可以返回m个状态,每个状态表示容量为j(j<=m)时选最多的宝物,而一个子节点中只可以选择一个状态进行转移,每个节点有若干个子节点,问题就转换为分组背包,几个子节点就是几个分组背包,体积是选几个地点,价值是宝物价值. 状态转移方程: dp[v][1] = Money[v]; (v为叶子节点)                    dp[v][j] = m