zoukankan      html  css  js  c++  java
  • 洛谷2014选课(树型dp)

    题目:https://www.luogu.org/problemnew/show/P2014

    千万注意遍历 j 和 k 的边界!

    0点很好用。

    siz很好用。

    #include<iostream>
    #include<cstdio>
    using namespace std;
    int n,m,a[305],f[305][305],cnt,l[305],siz[305],x;
    struct Node{
        int to,next;
    }edge[305];
    bool b[305];
    void add(int x,int y)
    {
        cnt++;
        edge[cnt].next=l[x];
        edge[cnt].to=y;
        l[x]=cnt;
    }
    void dfs(int cur)
    {
        if(b[cur])return;
        b[cur]=1;
        f[cur][1]=a[cur];
        siz[cur]++;
        for(int i=l[cur];i;i=edge[i].next)
        {
            int v=edge[i].to;
            dfs(v);
            for(int j=min(m,siz[cur]+siz[v]);j>1;j--)//////
                for(int k=max(j-siz[cur],0);k<=siz[v]&&k<j;k++)/////
                    f[cur][j]=max(f[cur][j],f[cur][j-k]+f[v][k]);
            siz[cur]+=siz[v];
        }
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d",&x,&a[i]);
            add(x,i);
        }
        for(int i=l[0];i;i=edge[i].next)
        {
            int v=edge[i].to;
            dfs(v);
            for(int j=min(m,siz[0]+siz[v]);j;j--)/////
                for(int k=max(j-siz[0],0);k<=siz[v]&&k<=j;k++)/////
                    f[0][j]=max(f[0][j],f[0][j-k]+f[v][k]);
            siz[0]+=siz[v];
        }
        printf("%d",f[0][m]);
        return 0;
    }

     后续的故事:

      考试的时候考出了原题,然后爆0……

      关键在于倒序。首先一定不能忘记倒序,因为实质上是省了一维的;

      而且这个倒序可以触及到1(甚至0也可以,因为有下面的k<j),这样的话在我们已有的所有 d[ ][ ] 中就已经包含了根节点的值了(别忘了提前赋 1 的值)。

      siz的更新和 j,k 边界仍然需要注意。

  • 相关阅读:
    Python3.5.2官方文档学习备忘录
    Linux下升级python版本
    役物,役于物
    各种编辑器添加注释快捷键
    Python3爬取百度百科(配合PHP)
    Python3向网页POST数据
    Python3爬取中文网址
    Python3批量爬取网页图片
    django中间件
    django创建上下文
  • 原文地址:https://www.cnblogs.com/Narh/p/8443423.html
Copyright © 2011-2022 走看看