• POJ 1155 TELE【树形DP】



    POJ 1155 TELE

    http://poj.org/problem?id=1155
    大意:某电台要广播一场比赛,该电台网络是由N个网点组成的一棵树,其中M个点为客户端,
    其余点为转发站。客户端i愿支付的钱为pay[i],每一条边需要的花费固定,问电台在保证不亏损的情况下,
    最多能使多少个客户端接收到信息?广播台所在的节点编号为1
    分析:树形DP
    1.user[i].dp[j]表示从转发站i开始计算,满足其子树中j个顾客的最大报酬
      分析节点i的孩子节点s
      a.放弃该孩子s,值不变
      b.取该孩子的若干的节点:user[i].dp[j-k]+user[s].dp[k]-cost[i][j](cost[i][j])为
       连通该边所需要付出的代价。
       综上:
       user[i].dp[j]=max(user[i].dp[j],user[i].dp[j-k]+user[s].dp[k]-cost[i][j]);
    2.对于客户端i,user[i].dp[1] = pay[i],即客户端服务一个顾客获得pay[i]的价值

    3.最多的服务客服数为user[1].dp[i]中大于0的最大i值,即广播台服务i个客户不亏损

    View Code
    1 #include<stdio.h>
    2 #include<string.h>
    3  constint N =3000+10;
    4  constint inf =999999;
    5 struct User
    6 {
    7 int pay;//若该节点为客户端,记录客户端提供的报酬
    8 int dp[N];//服务k个顾客的报酬
    9 }user[N];
    10 int father[N];
    11
    12 struct Edge
    13 {
    14 int v;
    15 int cost;//连接该边的花费
    16 Edge *next;
    17 }edge[N],*index[N];
    18
    19 bool visited[N];
    20 int ednum;
    21 inline void addEdge(int from,int to,int cost)
    22 {
    23 Edge *p =&edge[ednum++];
    24 p->cost = cost;
    25 p->v = to;
    26 p->next = index[from];
    27 index[from]=p;
    28 }
    29 inline int max(int a,int b)
    30 {
    31 return a>b?a:b;
    32 }
    33 int n,m;
    34 int dfs(int id)
    35 {
    36 if(visited[id]==true)return0;
    37 visited[id]=true;
    38 for(int i=1;i<=n;i++)
    39 {
    40 user[id].dp[i]=-inf;
    41 }
    42 user[id].dp[0]=0;
    43 if(index[id]==NULL)//叶子结点
    44 {
    45 user[id].dp[1]=user[id].pay;
    46 return1;//一个用户
    47 }
    48 int userNum =0;
    49 for(Edge *p = index[id];p;p=p->next)
    50 {
    51 if(visited[p->v]==false)
    52 {
    53 int sonuser = dfs(p->v);
    54 userNum+=sonuser;
    55 for(int i=userNum;i>0;i--)
    56 for(int j=1;j<=sonuser;j++)
    57 {
    58 user[id].dp[i]=max(user[id].dp[i],user[id].dp[i-j]+user[p->v].dp[j]-p->cost);
    59 }
    60 }
    61 }
    62
    63 return userNum;
    64
    65 }
    66 int main()
    67 {
    68
    69 while(scanf("%d%d",&n,&m)!=EOF)
    70 {
    71 for(int i=0;i<=n;i++)
    72 {
    73 visited[i]=false;
    74 index[i]=NULL;
    75 }
    76
    77 int mid = n-m,k,a,c;
    78 ednum =0;
    79 for(int i=1;i<=mid;i++)
    80 {
    81 scanf("%d",&k);
    82 while(k--)
    83 {
    84 scanf("%d%d",&a,&c);
    85 addEdge(i,a,c);
    86 }
    87 user[i].pay =0;
    88 }
    89
    90 for(int i = mid+1;i<=n;i++)
    91 scanf("%d",&user[i].pay);
    92
    93 dfs(1);
    94 for(int i=m;i>=0;i--)//寻找能使电台不亏损的最大服务顾客数
    95 {
    96 if(user[1].dp[i]>=0)
    97 {
    98 printf("%d\n",i);
    99 break;
    100 }
    101 }
    102 }
    103 return0;
    104 }

    树形DP类似的题还有:

    pku2342
    pku1655
    pku3107
    pku1463
    pku3345

    都是不错的题,适合新手入门,O(∩_∩)O~

  • 相关阅读:
    软件工程
    数字图像处理
    408笔记完
    408笔记完整考点篇
    解决CGLib动态代理测试不通过-Unable to load cache item
    支付宝支付与微信支付-系统化视频教程
    支付宝支付java版实战(含视频讲解)
    微信支付java版(含视频讲解)
    Java实现微信登录(网页授权)
    面试官问:实际生产中如何快速的测试接口(开发环境、测试环境、生产环境)
  • 原文地址:https://www.cnblogs.com/AndreMouche/p/1996163.html
Copyright © 2020-2023  润新知