• HDU 1011 Starship Troopers(树形dp)


    题意:给你一颗树,每个树都有一个花费值,一个获得值,然后给你m个人,一个人可以相当于20个bug,不满足20个也需要花费一个,最后问你最大可以获得多少价值

    思路:枚举现在的结点x的所有儿子,dp[i][j]代表结点i现在有j个人,dp[i][j]当然转移的是最大值,所以对于结点x,dp[x][j+k]=dp[x][j]+dp[son][k];因为是自下而上的进行dp,所以对于dp[x][j]的价值,在其他子结点的时候已经处理过了,就是01背包的思想(我觉得不是很容易理解,还是01背包学的太烂了),相当于暴力的枚举了每次的划分

    代码:

    #include <set>
    #include <map>
    #include <queue>
    #include <stack>
    #include <math.h>
    #include <vector>
    #include <string>
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <iostream>
    #include <algorithm>
    #define zero(a) fabs(a)<eps
    #define lowbit(x) (x&(-x))
    #define lson l,mid,rt<<1
    #define rson mid+1,r,rt<<1|1
    #define MOD 1000000007
    int max(int x,int y){return x>y?x:y;};
    int min(int x,int y){return x<y?x:y;};
    int max(int x,int y,int z){return max(x,max(y,z));};
    int min(int x,int y,int z){return min(x,min(y,z));};
    typedef long long LL;
    const double PI=acos(-1.0);
    const double eps=1e-8;
    const int inf=0x3f3f3f3f;
    const LL linf=0x3f3f3f3f3f3f3f3fLL;
    using namespace std;
    int read(){
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    
    const int maxn=100+7;
    int n,m;
    vector<int>mp[maxn];
    int a[maxn],val[maxn];
    int dp[maxn][maxn];
    bool vis[maxn];
    void dfs(int rt)
    {
        vis[rt]=true;
        for(int j=a[rt];j<=m;j++){
            dp[rt][j]=val[rt];
        }
        for(int i=0;i<mp[rt].size();i++){
            int now=mp[rt][i];
            if(vis[now])continue;
            dfs(now);
            for(int j=m;j>=a[rt];j--){
                for(int k=1;j+k<=m;k++){
                    if(dp[now][k])
                        dp[rt][j+k]=max(dp[rt][j+k],dp[rt][j]+dp[now][k]);
                }
            }
        }
    }
    int main()
    {
        while(~scanf("%d%d",&n,&m)){
            if(n==-1&&m==-1)break;
            for(int i=0;i<=n;i++)mp[i].clear();
            memset(dp,0,sizeof(dp));
            memset(vis,false,sizeof(vis));
            for(int i=1;i<=n;i++){
                scanf("%d%d",&a[i],&val[i]);
                a[i]=(a[i]+19)/20;
            }
            for(int i=0;i<n-1;i++){
                int t1,t2;
                scanf("%d%d",&t1,&t2);
                mp[t1].push_back(t2);
                mp[t2].push_back(t1);
            }
            if(m==0){
                puts("0");
                continue;
            }
            dfs(1);
            printf("%d
    ",dp[1][m]);
        }
        return 0;
    }
  • 相关阅读:
    Codeforces Round #650 (Div. 3)
    C. Count Triangles
    A National Pandemic (思维 + 树链剖分模版)
    扫描线专题
    扫描线模版
    莫队模版
    JS设计模式 -- 4种创建型模式
    滑动窗口的最大值 -- 单调队列
    JS链表实现栈和队列
    js数组扁平化的几种实现方式
  • 原文地址:https://www.cnblogs.com/lalalatianlalu/p/9021528.html
Copyright © 2020-2023  润新知