• [P1273] 有线电视网 (树形DP+分组背包)


    题意:给出一棵树,有边权,只有叶子节点有点权,求一个合法方案(选择走到哪几个叶子节点,且路径上的权值和 <= 要走到的叶子节点的点权和),使得选择的叶子节点数量尽量的多;

    解法:树形DP+分组背包;

    1.树形DP;这是一棵树,所以叫树形DP;

    2.分组背包;在这里主要是运用到了它的思想;我们可以设 f[i][j],表示 i节点选择了 j个叶子节点的费用最大值;假设现在在 x节点,它的下面有 n个叶子节点(不是它的儿子),那么我们就要处理出它选 1,2,3,……,n 个叶子节点的情况,但是由于这是一棵树,所以 x节点的状态又要由它的儿子节点转移过来,而它的儿子节点又包含有叶子节点……

    这不是很像是分组背包吗,我们只要将 x节点的每一个儿子看作是将要放进 x这个背包的的物品组别,而 x节点的儿子的叶子节点数量就是这个物品组别的物品数量,每次从 x节点的一棵子树递归回来,我们就可以进行一次 DP,每一次 DP就像是在这个这个儿子(组别)上进行一次分组背包操作,当递归完后,就可以得出答案啦;

    附上代码:

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    const int N = 3e3+10;
    const int inf = 0x3f3f3f3f;
    
    int n,m;
    int val[N];
    struct edge{
        int next,to,w;
    }a[N<<4];
    int head[N],cnt;
    int fa[N],size[N];
    int f[N][N],vis[N];
    
    void add(int u,int v,int w){
        a[++cnt]=(edge){head[u],v,w};
        head[u]=cnt;
    }
    
    int dfs(int x){
        if(val[x]){
            f[x][1]=val[x];
            return 1;
        }
        int sum=0,t;
        for(int i=head[x];i;i=a[i].next){
            int v=a[i].to;
            t=dfs(v);
            sum+=t;
            for(int j=sum;j>=1;--j)
            for(int k=1;k<=t;++k) f[x][j]=max(f[x][j],f[x][j-k]+f[v][k]-a[i].w);
        }
        return sum;
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1,k;i<=n-m;++i){
            scanf("%d",&k);
            for(int j=1,x,y;j<=k;++j){
                scanf("%d%d",&x,&y);
                add(i,x,y);
            }
        }
        for(int i=n-m+1;i<=n;++i) scanf("%d",&val[i]);
        memset(f,-inf,sizeof(f));
        for(int i=1;i<=n;++i) f[i][0]=0;
        dfs(1);
        for(int i=m;i>=1;--i){
            if(f[1][i]>=0){
                printf("%d",i);
                break;
            }
        }
        return 0;
    }
  • 相关阅读:
    VisualSVN 服务不能自动启动的问题
    "There is already an open DataReader associated with this Command which must be closed first"错误
    LINQ 中调用存储过程自动绑定列名
    vs2008中调试iis7.0托管的程序
    SQL SERVER 2005的一个怪问题: 在查询结果面板中编辑失败.
    在VS2003下把一个DataTable Update 到数据库
    帮人解决一个小问题:QQ空间登录时脚本错误造成无法登入
    关于Sys未定义错误
    多层母版页嵌套中, 内层母版页的事件默认不触发
    线程同步
  • 原文地址:https://www.cnblogs.com/nnezgy/p/11579277.html
Copyright © 2020-2023  润新知