zoukankan      html  css  js  c++  java
  • LA 4015 树形背包

    题目链接:https://vjudge.net/contest/164840#problem/D

    题意: 给一棵树,每条边上有一些权值,求 长度不超过 x ,最多能走多少个点;

    分析:

    考虑每一个节点,他可以一直走下去,也可以走回来而走到他的兄弟节点;

    状态定义: 

    d[x][j][0/1] 从 i 出发,走 j 个节点的最短距离;

    1、回来,这就是一个背包,更新当前节点;

    2、不回来,则是要考虑从哪个部分不回来;

     1 #include <bits/stdc++.h>
     2 
     3 using namespace std;
     4 
     5 int n;
     6 const int maxn = 550;
     7 const int inf = 0x3f3f3f3f;
     8 vector <int> g[maxn];
     9 int cnt[maxn];
    10 int son[maxn];
    11 
    12 int d[maxn][maxn][2];
    13 
    14 void dfs(int x) {
    15 
    16     for(int i=1; i<=n; i++)
    17         d[x][i][0] = d[x][i][1] = inf;
    18     d[x][1][0] = d[x][1][1] = 0;
    19 
    20 
    21     son[x] = 1;
    22     for(int i=0; i<g[x].size(); i+=2) {
    23         int y = g[x][i];
    24         int len = g[x][i+1];
    25         dfs(y);
    26 
    27         for(int j=son[x]; j>0; j--) {   ///这一重 相当于前面几个背包
    28             for(int k=1; k<=son[y]; k++) {  ///这一重 相当于当前这个背包中拿物品
    29                 d[x][j+k][1] = min(d[x][j+k][1],d[x][j][1]+d[y][k][1]+len*2);
    30                 d[x][j+k][0] = min(d[x][j+k][0],min(d[x][j][0]+d[y][k][1]+len*2,d[x][j][1]+d[y][k][0]+len));
    31             }
    32         }
    33 
    34         son[x] +=son[y];
    35     }
    36 }
    37 
    38 int main() {
    39     int cas = 1;
    40     while(scanf("%d",&n),n) {
    41         for(int i=0; i<=n; i++)
    42             g[i].clear();
    43 
    44         memset(cnt,0,sizeof(cnt));
    45         for(int i=0; i<n-1; i++) {
    46             int u,v,w;
    47             scanf("%d%d%d",&u,&v,&w);
    48             cnt[u]++;
    49             g[v].push_back(u);
    50             g[v].push_back(w);
    51         }
    52 
    53         int root = 0;
    54         for(int i=1; i<n; i++)
    55             if(!cnt[i])
    56                 root = i;
    57 
    58         dfs(root);
    59         int q,x;
    60         scanf("%d",&q);
    61         printf("Case %d:
    ",cas++);
    62         while (q--) {
    63             scanf("%d",&x);
    64             int ans = 1;
    65             for (int i = 1; i <= n; i++)
    66                 if (d[root][i][0] <= x)
    67                     ans = i;
    68             printf("%d
    ",ans);
    69         }
    70 
    71     }
    72     return 0;
    73 }
    View Code

    膜拜猫奴大牛;

  • 相关阅读:
    5.数组的使用,最值和反转
    4.下标越界及小结
    3.数组的三种初始化及简单内存分析
    html5版 音乐播放器
    百度网盘搜索
    HTML5扩展之微数据与丰富网页摘要
    Java 学习文章汇总
    业余草
    Catalan数
    Luogu P3004 [USACO10DEC]宝箱Treasure Chest
  • 原文地址:https://www.cnblogs.com/TreeDream/p/6900851.html
Copyright © 2011-2022 走看看