• NC50505 树形dp


    xg

    题意

       有一棵二叉苹果树,如果数字有分叉,一定是分两叉,即没有只有一个儿子的节点。这棵树 共N个节点,标号1至N,树根编号一定为1。 

     我们用一根树枝两端连接的节点编号描述一根树枝的位置。一棵有四根树枝的苹果树,因为 树枝太多了,需要剪枝。但是一些树枝上长有苹果,给定需要保留的树枝数量,求最多能留 住多少苹果。

    思路

      f[u][j]表示在以u为根的子树保留j个分支可以得到的最大苹果数量  

      nub[u]记录以u为根的数值和。

      f[i][j]的j只需要计算到min(nub【x】,Q)即可。

      f[x][i] = max(f[l][i-1]+e[x][l],f[r][i-1]+e[x][r]);表示当x对于两个根砍掉其中一只的最优解。

      

     如果两个都不砍的最优解

    #include <iostream>
    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <string>
    #include <map>
    #include <iomanip>
    #include <algorithm>
    #include <queue>
    #include <stack>
    #include <set>
    #include <vector> 
    // #include <bits/stdc++.h>
    #define fastio ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    #define sp ' '
    #define endl '
    '
    #define FOR(i,a,b) for( int i = a;i <= b;++i)
    #define bug cout<<"--------------"<<endl
    #define P pair<int, int>
    #define fi first
    #define se second
    #define pb(x) push_back(x)
    #define ppb() pop_back()
    #define mp(a,b) make_pair(a,b)
    #define ms(v,x) memset(v,x,sizeof(v))
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    #define repd(i,a,b) for(int i=a;i>=b;i--)
    #define sca3(a,b,c) scanf("%d %d %d",&(a),&(b),&(c))
    #define sca2(a,b) scanf("%d %d",&(a),&(b))
    #define sca(a) scanf("%d",&(a));
    #define sca3ll(a,b,c) scanf("%lld %lld %lld",&(a),&(b),&(c))
    #define sca2ll(a,b) scanf("%lld %lld",&(a),&(b))
    #define scall(a) scanf("%lld",&(a));
    
    
    using namespace std;
    typedef long long ll;
    ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
    ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
    ll powmod(ll a, ll b, ll mod){ll sum = 1;while (b) {if (b & 1) {sum = (sum * a) % mod;b--;}b /= 2;a = a * a % mod;}return sum;}
    
    const double Pi = acos(-1.0);
    const double epsilon = Pi/180.0;
    const int maxn = 110;
    int e[maxn][maxn];
    int n,Q;
    int f[110][110];
    int nub[maxn];
    void dfs(int x,int fa)
    {
        int l=0,r=0;
        for(int y = 1;y <= n; ++y){
            if(y == fa) continue;
            if(e[x][y] != -1){
                if(l == 0) l = y;
                else r = y;
            }
        }
        if(l == 0&&r==0){
            nub[x] = 1;
            return ;
        }
        dfs(l,x);
        dfs(r,x);
        nub[x] = nub[l]+nub[r]+2;
        rep(i,1,min(nub[x],Q)){
            f[x][i] = max(f[l][i-1]+e[x][l],f[r][i-1]+e[x][r]);
            rep(j,0,i-2){
                f[x][i] = max(f[x][i], f[l][j]+f[r][i-j-2]+e[x][l]+e[x][r]);
            }
        }
    
    }
    int main()
    {
        //freopen("input.txt", "r", stdin);
        sca2(n,Q);
        memset(e,-1,sizeof(e));
        rep(i,1,n-1){
            int x,y,z;
            sca3(x,y,z);
            e[x][y] = z;
            e[y][x] = z;
        }
    
        dfs(1,0);
    
        int ans = 0;
    
        printf("%d
    ",f[1][Q] );
    
    }

      

      

  • 相关阅读:
    C#中的配置文件自定义解析 [转帖]
    pagevisibility event
    [转] 翻译:web制作、开发人员需知的Web缓存知识
    离开和新的开始
    为什么我要自己写html5游戏引擎
    html5游戏长宽设置
    防止横竖屏时,iphone自动缩放的一段代码
    image to base64 工具
    一段代码,给游戏添加统一的封面和旋屏提示
    程序员应该具备的知识和技术(转)
  • 原文地址:https://www.cnblogs.com/jrfr/p/13512446.html
Copyright © 2020-2023  润新知