zoukankan      html  css  js  c++  java
  • Vijos 1180 (树形DP+背包)

    题目链接https://vijos.org/p/1180

    题目大意:选课。只有根课选了才能选子课,给定选课数m, 问最大学分多少。

    解题思路

    树形背包。cost=1。

    且有个虚根0,取这个虚根也要cost,所以最后的结果是dp[0][m+1]。

    本题是cost=1的特殊背包问题,在两个for循环上有一个优化。

    for(f+1...j....cost)

      for(1....k...j-cost)

    其中f为当前已经dfs子结点个数。之所以+1,是因为根要预留一个空间。

    f+=dfs(t),dfs(t)返回的是子点t的f+1。

    其实可以直接把f+1写成m+1, 不过要多好多次没必要的循环。

    这种写法在POJ 1155点数量庞大时,将起决定性作用。

    #include "iostream"
    #include "cstdio"
    #include "cstring"
    using namespace std;
    #define maxn 305
    int n,m,root,x;
    int dp[maxn][maxn],head[maxn],w[maxn],tol;
    struct Edge
    {
        int to,next;
    }e[maxn];
    void addedge(int u,int v)
    {
        e[tol].to=v;
        e[tol].next=head[u];
        head[u]=tol++;
    }
    int dfs(int root)
    {
        int i=root,f=0,cost=1;
        for(int i=cost;i<=m;i++) dp[root][i]=w[root];
        for(int a=head[root];a!=-1;a=e[a].next)
        {
            int t=e[a].to;
            f+=dfs(t);
            for(int j=f+1; j>=cost; j--)
                for(int k=1; k<=j-cost; k++)
                    dp[i][j]=max(dp[i][j],dp[i][j-k]+dp[t][k]);
        }
        return f+cost; //¸ùÒ²ÏûºÄ1
    }
    int main()
    {
        //freopen("in.txt","r",stdin);
        scanf("%d%d",&n,&m);
        memset(head,-1,sizeof(head));
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d",&x,&w[i]);
            addedge(x,i);
        }
        dfs(0);
        printf("%d
    ",dp[0][m+1]);
    }

    Accepted, time = 22 ms, mem = 924 KiB, score = 100

  • 相关阅读:
    Qt计算器开发(三):执行效果及项目总结
    [HNOI2019]校园旅行
    How to fix nuget Unrecognized license type MIT when pack
    How to fix nuget Unrecognized license type MIT when pack
    git 通过 SublimeMerge 处理冲突
    git 通过 SublimeMerge 处理冲突
    git 上传当前分支
    git 上传当前分支
    gif 格式
    gif 格式
  • 原文地址:https://www.cnblogs.com/neopenx/p/4032015.html
Copyright © 2011-2022 走看看