zoukankan      html  css  js  c++  java
  • 依赖背包变形(经典)——poj1155

    这个题用优化后的依赖背包做难以实现,所以用常规的泛化物品的和来做即可

    每个节点的容量定义为这个节点下的叶子结点个数,dp[u][j]用来表示节点u下选取j个物品的最大收益,最后从m-0查询dp[1][i],一旦发现是非负数,i则是答案

    需要注意的地方:初始化时将所有的dp[i][0]都赋值为0,一个都不选,代价当然是0

            dfs遇到u是叶子结点,那么dp[u][1]定义为这个结点的权值,其余状态用-inf来表示不可达

            其余状态全部赋初始值为-inf,表示目前不可达

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    #define N 3005
    struct Edge{int to,nxt,w;}e[N<<1];
    int head[N],tot,n,m;
    void add(int u,int v,int w){
        e[tot].to=v;e[tot].nxt=head[u];e[tot].w=w;head[u]=tot++;
    }
    int dp[N][N],a[N],size[N];
    void dfs1(int u,int pre){
        for(int i=head[u];i!=-1;i=e[i].nxt){
            int v=e[i].to;
            if(v==pre)continue;
            dfs1(v,u);size[u]+=size[v];
        }
    }
    void dfs2(int u,int pre){
        if(a[u]){dp[u][1]=a[u];return;}
        for(int i=head[u];i!=-1;i=e[i].nxt){
            int v=e[i].to;
            if(v==pre)continue;
            dfs2(v,u);
            for(int j=size[u];j>=0;j--)
                for(int k=0;k<=size[v];k++)
                    dp[u][j]=max(dp[u][j],dp[v][k]-e[i].w+dp[u][j-k]);
        }
    }
    int main(){
        memset(head,-1,sizeof head); 
        cin>>n>>m;
        for(int i=1;i<=n-m;i++){
            int k,v,w;cin>>k;
            while(k--){
                cin>>v>>w;
                add(i,v,w);add(v,i,w);
            }
        }
        for(int i=n-m+1;i<=n;i++)
            cin>>a[i],size[i]=1;
        memset(dp,-0x3f,sizeof dp);
        for(int i=1;i<=n;i++)dp[i][0]=0;
        dfs1(1,1);dfs2(1,1);
        
        for(int i=m;i>=0;i--)
            if(dp[1][i]>=0){
                cout<<i<<endl;
                break;
            }
    }
  • 相关阅读:
    js 练习,点击计算三个数的最大值,省级联动
    CSS 笔记
    CSS练习
    Html 学习笔记
    MySQL 执行计划详解
    别人家的元数据系统是怎么设计的
    深入浅出Dubbo RPC
    算法的时间复杂度和空间复杂度详解
    序列化 & 反序列化
    MySQL的四种隔离级别
  • 原文地址:https://www.cnblogs.com/zsben991126/p/11385191.html
Copyright © 2011-2022 走看看