zoukankan      html  css  js  c++  java
  • poj 1155(树形dp)

    题意:有一个有线电视网络叶子结点是用户,每个用户有一个愿意支付的金额。然后每条边都有话费。问公司在不亏本的情况下最多能满足多少用户。

    思路:dp[v][j] = max(dp[v][j], dp[v][j-k]+dp[x][k]-edge(v, x))

    其实就是背包问题,但是一开始TLE了一次,这里要有个优化处理一个节点之前需要初始化一下他最多接着几个用户。这样就AC了。

    代码如下:

     1 #include <stdio.h>
     2 #include <string.h>
     3 #include <iostream>
     4 #include <algorithm>
     5 #include <vector>
     6 #include <queue>
     7 #include <set>
     8 #include <map>
     9 #include <string>
    10 #include <math.h>
    11 #include <stdlib.h>
    12 #include <time.h>
    13 #define MP(a, b) make_pair(a, b)
    14 #define PB(a) push_back(a)
    15 using namespace std;
    16 const int LEN = 3010;
    17 const int INF = 0x3f3f3f3f;
    18 typedef pair<int, int> pii;
    19 int n, m, dp[LEN][LEN], vex[LEN], num[LEN];
    20 vector<pii> Map[LEN];
    21 
    22 void dfs(int v, int fa){
    23     if(v > n-m && v <= n) dp[v][1] = vex[v];
    24     for(int i=0; i<Map[v].size(); i++){
    25         int x = Map[v][i].first;
    26         if(x != fa){
    27             dfs(x, v);
    28             num[v] += num[x];
    29             for(int j=num[v]; j>=0; j--){
    30                 for(int k=0; k<=num[x]; k++){
    31                     if(j - k >= 0 && dp[x][k] != -INF && dp[v][j-k] != -INF)
    32                            dp[v][j] = max(dp[v][j], dp[v][j-k]+dp[x][k]-Map[v][i].second);
    33                 }
    34             }
    35         }
    36     }
    37 }
    38 
    39 void init(){
    40     for(int i=0; i<LEN; i++)Map[i].clear();
    41     memset(num, 0, sizeof num);
    42     for(int i=0; i<LEN ;i++){
    43         for(int j=0; j<LEN; j++){
    44             dp[i][j] = -INF;
    45             if(j == 0) dp[i][j] = 0;
    46         }
    47     }
    48 }
    49 
    50 int main()
    51 {
    52 //   freopen("in.txt","r",stdin);
    53     //freopen("out.txt","w",stdout);
    54     
    55     int a, b, tn;
    56     while(scanf("%d%d", &n, &m)!=EOF){
    57         init();
    58         for(int i=1; i<=n-m; i++){
    59             scanf("%d", &tn);
    60             for(int j=0; j<tn; j++){
    61                 scanf("%d%d", &a, &b);
    62                 Map[i].PB(MP(a, b));
    63                 Map[a].PB(MP(i, b));
    64             }
    65         }
    66         for(int i=n-m+1; i<=n ;i++){
    67             num[i] = 1;
    68             scanf("%d", &vex[i]);
    69         }
    70         dfs(1, -1);
    71         int ans;
    72         for(int i=m; i>=0; i--){
    73             if(dp[1][i] >= 0){
    74                 ans = i;
    75                 break;
    76             }
    77         }
    78         printf("%d
    ", ans);
    79     }
    80     return 0;
    81 
    82 }
    View Code
  • 相关阅读:
    【HDOJ】2267 How Many People Can Survive
    【HDOJ】2268 How To Use The Car
    【HDOJ】2266 How Many Equations Can You Find
    【POJ】2278 DNA Sequence
    【ZOJ】3430 Detect the Virus
    【HDOJ】2896 病毒侵袭
    求奇数的乘积
    平方和与立方和
    求数列的和
    水仙花数
  • 原文地址:https://www.cnblogs.com/shu-xiaohao/p/3704455.html
Copyright © 2011-2022 走看看