• HDU 4169 UVALive 5741 Wealthy Family


    树形背包。DP递推的思路很简单....

    但是由于节点有15万个,先不论空间复杂度,这样开dp数组 dp[150000+10][300+10],如果初始化是memset(dp,-1,sizeof dp),则必然超时。

    所以需要一个状态数剪枝。。。即记录这个节点最多组合的数量。

    UVALive是不限制内存的,所以dp[150000+10][300+10] 能够AC,HDU 4169 限制了内存大小,需要优化空间复杂度。

    内存优化之后的代码,HDU上C++能AC,G++依旧MLE。

    #include<cstdio>
    #include<cstring>
    #include<queue>
    #include<algorithm>
    using namespace std;
    
    const int maxn=150000+10;
    struct Node
    {
        int val;
        int fa;
        queue<int *>Q;
        vector<int>f;
    }node[maxn];
    int n,k,root;
    int cnt[maxn];
    int ans;
    
    void init()
    {
        memset(cnt,0,sizeof cnt);
        for(int i=1;i<=n;i++)
        {
            while(!node[i].Q.empty()) node[i].Q.pop();
            node[i].f.clear();
        }
    }
    
    void read()
    {
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d",&node[i].fa,&node[i].val);
            if(!node[i].fa) root=i;
            else node[node[i].fa].f.push_back(i);
        }
    }
    
    void dfs(int now)
    {
        if(!node[now].f.size())
        {
            cnt[now]=1;
            int *p=new int[cnt[now]+2];
            p[0]=0; p[1]=node[now].val;
            node[node[now].fa].Q.push(p);
            delete[] p;
            return;
        }
    
        for(int i=0;i<node[now].f.size();i++)
        {
            int id=node[now].f[i];
            cnt[now]=cnt[now]+cnt[id];
        }
    
        cnt[now]=min(k,cnt[now]);
    
        int *p=new int[cnt[now]+2];
    
        p[0]=0;
        for(int i=1;i<=cnt[now];i++) p[i]=-1;
    
        int id=0;
        while(!node[now].Q.empty())
        {
            int *head=node[now].Q.front();
            node[now].Q.pop();
    
            for(int j=cnt[now];j>=0;j--)
                for(int s=0;s<=j&&s<=cnt[node[now].f[id]];s++)
                    if(head[s]!=-1&&p[j-s]!=-1)
                        p[j]=max(p[j],head[s]+p[j-s]);
            id++;
        }
        p[1]=max(p[1],node[now].val);
    
        node[node[now].fa].Q.push(p);
    
        if(now==1)
        {
            if(cnt[1]<k||p[k]==-1) ans=-1;
            else ans=p[k];
        }
    
        delete[] p;
        return;
    }
    
    void work()
    {
        dfs(root);
        if(ans==-1) printf("impossible
    ");
        else printf("%d
    ",ans);
    }
    
    int main()
    {
        while(~scanf("%d%d",&n,&k))
        {
            init();
            read();
            work();
        }
        return 0;
    }

    二维DP写法。HDU 上MLE的。UvaLive能过的。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    
    int n, k;
    int root;
    const int maxn = 150000 + 10;
    struct Edge
    {
        int now;
        int next;
    }e[maxn];
    int head[maxn];
    int cnt[maxn];
    int val[maxn];
    int dp[maxn][300 + 10];
    int q;
    
    void init()
    {
        q=0;
        for(int i=1;i<=n;i++) head[i]=-1;
    }
    
    void read()
    {
        for (int i = 1; i <= n; i++)
        {
            int fa;
            scanf("%d%d", &fa, &val[i]);
            if (!fa) root = i;
            else
            {
                e[q].now=i, e[q].next=head[fa];
                head[fa]=q, q=q+1;
            }
        }
    }
    
    void dfs(int now)
    {
        cnt[now]=0;
        if (head[now]==-1)
        {
            cnt[now]=1;
            dp[now][1] = val[now];
            return;
        }
    
        for (int i = head[now]; i!=-1; i=e[i].next)
        {
            int id = e[i].now;
            dfs(id);
            cnt[now]=cnt[now]+cnt[id];
        }
    
        cnt[now]=min(cnt[now],k);
    
         for(int i=0;i<=cnt[now];i++) dp[now][i]=-1;
            dp[now][0]=0;
    
        for (int i = head[now]; i!=-1; i=e[i].next)
        {
            int id = e[i].now;
            for(int j=cnt[now];j>=0;j--)
                for(int s=0;s<=j&&s<=cnt[id];s++)
                    if(dp[id][s]!=-1&&dp[now][j-s]!=-1)
                        dp[now][j]=max(dp[now][j],dp[id][s]+dp[now][j-s]);
        }
        dp[now][1]=max(val[now],dp[now][1]);
    }
    
    void work()
    {
        dfs(root);
        if (cnt[root]<k||dp[root][k] == -1) printf("impossible
    ");
        else printf("%d
    ", dp[root][k]);
    }
    
    int main()
    {
        while (~scanf("%d%d", &n, &k))
        {
            init();
            read();
            work();
        }
        return 0;
    }
  • 相关阅读:
    NOsql总结
    关于Swift中的指针的那些事
    并发控制的概念
    并发控制--Concurrency control--乐观、悲观及方法
    数据库的三大系统
    数据库沉思录
    代码结构化(分层)阅读
    代码阅读困难的原因
    数据库锁与并发
    SQLite事务、错误与自动回滚
  • 原文地址:https://www.cnblogs.com/zufezzt/p/5185861.html
Copyright © 2020-2023  润新知