POJ 1155 TELE 树形dp

原创 2012年03月27日 20:40:56

http://poj.org/problem?id=1155

题意:某电台要广播一场比赛,该电台网络是由N个网点组成的一棵树,其中M个点为客户端,其余点为转发站。客户端i愿支付的钱为pay[i],每一条边需要的花费固定,问电台在保证不亏损的情况下,最多能使多少个客户端接收到信息?广播台所在的节点编号为1。

思路:树形dp。 用dp[root][d] 表示以root为根的子树中,保留d个用户的最大利润,由于每个结点的孩子的数目并不是最多只有两个,因此在求dp[root][d]的时候要进行一次横向的dp,即对root的所有孩子进行一个背包,在具体实现的时候我们可以一次求出root的所有可能d的最大利润(在背包dp的时候一起求出)。

需要注意的几点:1、树最好用邻接矩阵存储,这样可以节约寻找root孩子的时间;

     2、用一个num[ ]数组存储每个root状态数, 即d的最大值,这样比每次都从M开始求用时会少,避免超时。


代码:

#include<stdio.h>
#include<string.h>
#define INF 100000000
#define MAX(a,b) (a) > (b) ? (a) : (b)
int N ,M ;
int pay[3010] ;
int dp[3010][3010] ;
struct Node{
	int d ; 
	int next ;
	int n ;	
}edge[3010] ;
int root[3010] ;
int cnt ;
int num[3010] ;			//存放每个结点的状态种数 

void dfs(int u){
	if(u > N-M){
		num[u] = 1 ;
		dp[u][1] = pay[u] ;
		return ;	
	}	
	dp[u][0] = 0 ;
	for(int i=root[u]; i!=-1; i=edge[i].next){
		int v = edge[i].n ;
		int d = edge[i].d ;
		dfs(v) ;
		num[u] += num[v] ;
		for(int j=num[u];j>=0;j--){			//孩子的背包 
			for(int k=1;j-k>=0 && k<=num[v];k++){
				dp[u][j] = MAX(dp[u][j] , dp[u][j-k]+dp[v][k]-d );	
			}
		}
	}
}
void add(int u , int v, int d){
	edge[cnt].d = d ;
	edge[cnt].n = v ;
	edge[cnt].next = root[u] ;
	root[u] = cnt ++ ;	
}
int main(){
	int a , b ,c ,i, j ;
	while(scanf("%d %d",&N,&M) == 2){
		memset(root , -1  ,sizeof(root) );
		cnt = 0 ;
		for(i=1;i<=N-M;i++){
			scanf("%d",&a);	
			for(j=0;j<a;j++){
				scanf("%d %d",&b,&c);
				add(i,b,c);
			}
		}	
		for(i=N-M+1;i<=N;i++){
			scanf("%d",&pay[i]);				
		}
		for(int i=1;i<=N;i++){
			for(int j=0;j<=M;j++)
				dp[i][j] = -INF ;	
		}
		memset(num , 0 ,sizeof(num));
		dfs(1) ;
		for(int i=num[1];i>=0;i--){
			if(dp[1][i] >= 0){
				printf("%d\n",i);
				break ;	
			}	
		}      
	}	
	return 0 ;	
}


poj1155 TELE(树形dp+背包)

TELE Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 4344   Accepted:...
  • d_x_d
  • d_x_d
  • 2015年11月16日 20:06
  • 1517

(中等) 树形dp POJ 1155 TELE

TELE Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 3190 Accepted: 1640 Descripti...
  • wsx1754175
  • wsx1754175
  • 2014年02月08日 09:52
  • 297

POJ 1155 TELE (树形背包)

题目链接:http://poj.org/problem?id=1155 题目大意:给出一棵n个结点的树,每个叶子结点有一个权值,每条边也有一个权值。求一个叶子节点数最大的集合,使得该集合中所...
  • Interstellar_
  • Interstellar_
  • 2017年03月31日 08:21
  • 120

poj 1848 Tree(树形DP,太难了,三种状态,四种状态转换)

1、http://poj.org/problem?id=1848 2、题目大意: 给出一棵树,现在要往这棵树上加边,使得所有的点都在环中,且每个点只能属于一个环 分析:参考http://hi.b...
  • sdjzping
  • sdjzping
  • 2014年01月21日 17:28
  • 1222

poj 1155 (树形DP)

poj 1155 题目:http://poj.org/problem?id=1155 树形DP。d [ u ][ i ]表示以u为根节点,用户数为i 的最大收益。状态转移方程:d[ u ][ i ] ...
  • u010794465
  • u010794465
  • 2013年07月19日 11:07
  • 549

poj 1155 TELE 基础题,树形背包

有一个电视台要用电视网络转播节目。这种电视网络是一树,树的节点为中转站或者用户。树节点的编号为1~N,其中1为总站,2~(N-M)为中转站,(总站和中转站统称为转发站)N-M+1~N为用户,电视节目从...
  • yskyskyer123
  • yskyskyer123
  • 2015年12月30日 20:29
  • 228

POJ 1155 - TELE 树形DP(泛化背包转移)..

dp[x][y]代表以x为根的子树..连接了y个终端用户(叶子)..所能获得的最大收益...     dp[x][ ]可以看成当根为x时..有个背包空间为0~m...每个空间上记录了到到达这个空间的最...
  • kk303
  • kk303
  • 2013年07月20日 14:30
  • 749

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

/*     这道题还不错,自己想出了思路过得也比较快,也得出了一个小经验,以后写这种题先把关键部分伪代码写出来这样会快很多而且     不那么容易出错,省去很多的调试时间     这道题就是转...
  • crazy__C
  • crazy__C
  • 2015年04月06日 00:15
  • 896

【树形DP】 POJ 1155 / 1947 树形背包

POJ 1155 / 1947 树形背包(DP) POJ 1155 TELE POJ 1947 Rebuilding Roads
  • du489380262
  • du489380262
  • 2013年08月02日 19:16
  • 505

树形动态规划(树状DP)小结

树状动态规划定义 之所以这样命名树规,是因为树形DP的这一特殊性:没有环,dfs是不会重复,而且具有明显而又严格的层数关系。利用这一特性,我们可以很清晰地根据题目写出一个在树(型结构)上的记忆化搜索...
  • txl16211
  • txl16211
  • 2015年04月29日 23:10
  • 9197
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:POJ 1155 TELE 树形dp
举报原因:
原因补充:

(最多只允许输入30个字)