poj 1155-TELE 树形dp

poj 1155-TELE 链接:http://poj.org/problem?id=1155

题意是说一个电视台要转播一场重要的足球赛事,电视台有m个客户端,每个客户端愿意为了观看电视支付一定的费用,但是由于转播塔有限,而且在转播塔到客户端之间需要一定的转播费用,所以电视台为了不赔钱可能无法让所有的客户端都看到赛事,求的是在不赔钱的前提前如何保证让最多的人看到电视

典型的树形dp问题,dp[i][j]表示的是在以i为根的树当中选取j个人看电视的最大利润,那么就类似于背包问题了。不过要有一个临时数组去存上一步的状态。

View Code
 1 #include<iostream>
2 #include<cstdio>
3 #include<cstring>
4 #include<vector>
5 #define MAX 3010
6 #define inf 0x3f3f3f3f;
7 using namespace std;
8 int w[MAX];
9 int num[MAX];
10 int dp[MAX][MAX];
11 int n,m,e;
12 int max(int a,int b)
13 {
14 return a>b?a:b;
15 }
16 int edgev[MAX];
17 vector<int> g[MAX];
18 void dfs(int u)
19 {
20 dp[u][0]=0;
21 if(u>n-m)
22 {
23 num[u]=1;
24 dp[u][1]=w[u];
25 return;
26 }
27 int temp[MAX];
28 int i,j,k;
29 int size=g[u].size();
30 for(i=0;i<size;i++)
31 {
32 int v2=g[u][i];
33 dfs(v2);
34 for(j=0;j<=num[u];j++)
35 temp[j]=dp[u][j];
36 for(j=0;j<=num[u];j++)
37 for(k=1;k<=num[v2];k++)
38 {
39 dp[u][j+k]=max(dp[u][j+k],temp[j]+dp[v2][k]-edgev[v2]);
40 }
41 num[u]+=num[v2];
42 }
43 }
44 int main()
45 {
46 int i,j,k;
47 int t;
48 int v1,va;
49 while(scanf("%d%d",&n,&m)!=EOF)
50 {
51 for(i=0;i<=n-m;i++)
52 g[i].clear();
53 for(i=1;i<=n-m;i++)
54 {
55 scanf("%d",&t);
56 while(t--)
57 {
58 scanf("%d%d",&v1,&va);
59 edgev[v1]=va;
60 g[i].push_back(v1);
61 }
62 }
63 for(i=n-m+1;i<=n;i++)
64 scanf("%d",&w[i]);
65 for(int i= 1; i <= n; ++i)
66 for(int j = 1; j <= m; ++j)
67 dp[i][j] = -inf;
68 memset(num,0,sizeof(num));
69 dfs(1);
70 for(i=m;i>=0;i--)
71 if(dp[1][i]>=0)
72 {
73 printf("%d\n",i);
74 break;
75 }
76 }
77 return 0;
78 }

 

posted @ 2012-04-05 09:01  zhenhai  阅读(315)  评论(0编辑  收藏  举报