POJ1155 TELE(树形DP)

来源:互联网 发布:广告优化师的工作内容 编辑:程序博客网 时间:2024/06/06 14:21

题目大意:

一个电视台转播比赛,电视网络类似于树,树的节点为中转站或者用户

节点的编号为1~N,其中1为总站,2到(N-M)为中转站,(N-M+1)到N为用户

节点到节点间转移信号需要给定的费用,且每个用户愿意出给定的钱付费

在电视台不亏本的前提下,求最多可以让多少用户看到比赛


树形背包DP,容量为该点的子节点数量,价值为费用

状态 dp[u][j] 代表根节点为u含有j个子节点的子树所获得的费用(负为亏)

状态转移 dp[u][j]=max(dp[u][j],dp[u][j-k]+dp[v][k]-edge[i].w)


#include <stdio.h>#include <string.h>#define MAXN 3010struct Node{int v,w,next;}edge[MAXN*MAXN];int dp[MAXN][MAXN];int num[MAXN];//容量int head[MAXN];int max(int a,int b){return a>b?a:b;}void dfs(int u){int i,j,k,v;for(i=head[u];i!=-1;i=edge[i].next){v=edge[i].v;dfs(v);num[u]+=num[v];for(j=num[u];j>=1;j--)//背包 需要逆向for(k=1;k<=num[v];k++)dp[u][j]=max(dp[u][j],dp[u][j-k]+dp[v][k]-edge[i].w);}}int main(){int i,j,n,m,k,cnt=0;memset(head,-1,sizeof(head));scanf("%d%d",&n,&m);for(i=1;i<=n-m;i++){scanf("%d",&k);while(k--){scanf("%d%d",&edge[cnt].v,&edge[cnt].w);edge[cnt].next=head[i];head[i]=cnt++;}}    for(i=1;i<=n;i++)        for(j=1;j<=m;j++)            dp[i][j]=-1e9;//因为状态有负值 所以不能为0for(i=n-m+1;i<=n;i++){num[i]=1;scanf("%d",&dp[i][1]);}dfs(1);for(i=num[1];i>=0;i--)if(dp[1][i]>=0)break;printf("%d",i);return 0;}


0 0
原创粉丝点击