zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    背水一战 Windows 10 (61)
    背水一战 Windows 10 (60)
    背水一战 Windows 10 (59)
    背水一战 Windows 10 (58)
    背水一战 Windows 10 (57)
    背水一战 Windows 10 (56)
    背水一战 Windows 10 (55)
    背水一战 Windows 10 (54)
    背水一战 Windows 10 (53)
    背水一战 Windows 10 (52)
  • 原文地址:https://www.cnblogs.com/zufezzt/p/5185861.html
Copyright © 2011-2022 走看看