zoukankan      html  css  js  c++  java
  • POJ 1155 TELE 树形背包问题

    题目描述看的莫名其妙,很久才看懂。

    就是很裸的树形背包问题吧,状态是dp(i,j)表示节点i取到j个客户能得到的最大收益。

    注意一开始初始化的时候所有j为0的时候应该是0,然后其他值都要初始化成负无穷,因为收益有可能是负值。

    然后做01背包的时候注意方向,防止出现取某一个元素多次

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <map>
    #include <set>
    #include <vector>
    #include <string>
    #include <queue>
    #include <deque>
    #include <bitset>
    #include <list>
    #include <cstdlib>
    #include <climits>
    #include <cmath>
    #include <ctime>
    #include <algorithm>
    
    using namespace std;
    
    #define MP make_pair
    #define PB push_back
    typedef long long LL;
    typedef unsigned long long ULL;
    typedef vector<int> VI;
    typedef pair<int,int> pii;
    const int INF = INT_MAX / 3;
    const double eps = 1e-8;
    const LL LINF = 1e17;
    const double DINF = 1e60;
    const int maxn = 3000 + 5;
    //dp(i,j) 第i个节点找到j个客户的最大收益
    int dp[maxn][maxn],N,M;
    int first[maxn],nxt[maxn],w[maxn],v[maxn],ecnt;
    int P[maxn],ccnt[maxn];
    
    void adde(int uu,int vv,int ww) {
        w[ecnt] = ww; v[ecnt] = vv; nxt[ecnt] = first[uu]; first[uu] = ecnt++;
    }
    
    int getcnt(int now) {
        if(first[now] == -1) return ccnt[now] = 1;
        for(int i = first[now];~i;i = nxt[i]) {
            ccnt[now] += getcnt(v[i]);
        }
        return ccnt[now];
    }
    
    void dfs(int now) {
        //printf("now is %d
    ",now);
        if(first[now] == -1) {
            //如果当前为叶子节点
            dp[now][0] = 0; dp[now][1] = P[now];
        }
        else {
            for(int i = first[now];~i;i = nxt[i]) {
                dfs(v[i]);
                //更新所有状态,01背包
                for(int j = ccnt[now];j >= 0;j--) {
                    //枚举是从下一个节点拿几个,这里注意是01背包,从大到小更新
                    for(int k = 0;k <= ccnt[v[i]] && k <= j;k++) {
                        dp[now][j] = max(dp[now][j],
                                dp[v[i]][k] + dp[now][j - k] - w[i]);
                        //printf("k is %d %d + %d - %d
    ",k,dp[v[i]][k],dp[now][j - k],w[i]);
                    }
                    //printf("dp[%d][%d] = %d
    ",now,j,dp[now][j]);
                }
            }
        }
    }
    
    
    int main() {
        while(scanf("%d%d",&N,&M) != EOF) {
            memset(first,-1,sizeof(first));
            memset(ccnt,0,sizeof(ccnt));
            ecnt = 0;
            for(int i = 1;i <= N - M;i++) {
                int k; scanf("%d",&k);
                for(int j = 1;j <= k;j++) {
                    int ak,ck; scanf("%d%d",&ak,&ck);
                    adde(i,ak,ck);
                }
            }
            for(int i = N - M + 1;i <= N;i++) scanf("%d",&P[i]);
            getcnt(1);
            for(int i = 1;i <= N;i++) {
                for(int j = 0;j <= ccnt[i];j++) dp[i][j] = -INF;
                dp[i][0] = 0;
            }
            dfs(1);
            int ans = 0;
            for(int i = 0;i <= ccnt[1];i++) if(dp[1][i] >= 0) ans = i;
            printf("%d
    ",ans);
        }
        return 0;
    }
    

      

  • 相关阅读:
    在web项目下注册MySQL数据库驱动失败
    Servlet 调用过程
    请求时参数到后台解码时会出现乱码问题
    Request 部分功能
    dom4j增删改查
    微信消息处理JAXP-sax解析
    微信消息处理JAXP-dom解析
    inputstream与其他格式的转换
    微信消息处理
    将Gridview导出到Excel
  • 原文地址:https://www.cnblogs.com/rolight/p/3901202.html
Copyright © 2011-2022 走看看