• HDU


    题意

    n类工作,每类有m个独立的工作和属性s,s有必做一个,最多只能做一个和任意选择这三个属性.每个独立的工作有耗时和收益两个属性.求在t时间内的最大收益.

    分析

    (dp[i][j])表示在前i类任务j耗时内的最大收益.若不加属性s,就是一个单纯的分组背包.现在对不同的s,有不同的状态转移方程.

    1.该类必选.

    (dp[i][j] = max(dp[i][j],dp[i-1][j-w]+v,dp[i][j-w]+v)),其中(dp[i][j]) 表示不选,我们不想让它不选,所以将(dp[i])全部初始化为-INF,这样状态就会优先从已选物品的状态转移过来.

    2.最多选一个

    相当于对这类物品做一次0-1背包,但是状态是在之前一层基础上的.向将前一层的值赋给当前层.再做状态转移:(dp[i][j] = max(dp[i][j], dp[i-1][j-w]+v))

    3.任意选择

    此时仍有状态转移:(dp[i][j] = max(dp[i][j],dp[i-1][j-w]+v,dp[i][j-w]+v)),其中(dp[i][j]).也是需要将上一层的dp值覆盖到当前层.

    #include<bits/stdc++.h>
    #define PII pair<int,int>
    #define MP make_pair
    #define X first
    #define Y second
    using namespace std;
    const int maxn = 1e2+5;
    const int INF = 0x3f3f3f3f;
    typedef long long LL;
    int dp[maxn][maxn];
    
    vector<PII> vz[maxn];
    
    int main()
    {
        #ifndef ONLINE_JUDGE
            freopen("in.txt", "r", stdin);
            freopen("out.txt", "w", stdout);
        #endif
        int n,W;
        while(scanf("%d %d",&n, &W)==2){
            memset(dp,0,sizeof(dp));
            for(int i=0;i<maxn;++i) vz[i].clear();
            int sum = 0;
    
            for(int i=1,m,s;i<=n;++i){
                scanf("%d %d",&m, &s);
                while(m--){
                    int c,g;
                    scanf("%d %d",&c, &g);
                    vz[i].push_back(MP(c,g));
                }
                if(s==0){
                    memset(dp[i],-INF,sizeof(dp[i]));
                    for(int k =0,sz = vz[i].size();k<sz;++k){
                        int w = vz[i][k].X;
                        for(int j= W; j>=w;--j){
                            int v = vz[i][k].Y;
                            dp[i][j] = max(dp[i][j], max(dp[i-1][j-w]+v,
                                    dp[i][j-w]+v));
                        }
                    }
                }
                else if(s==1){
                    for(int j= 0;j<=W;++j) dp[i][j] = dp[i-1][j];
                    for(int k = 0,sz = vz[i].size();k<sz;++k){
                        int w = vz[i][k].X;
                        for(int j=W;j>=w;--j){
                            int v = vz[i][k].Y;
                            dp[i][j] = max(dp[i][j],dp[i-1][j-w]+v);
                        }
                    }
                }
                else{
                    for(int j= 0;j<=W;++j) dp[i][j] = dp[i-1][j];
                    for(int k = 0,sz = vz[i].size();k<sz;++k){
                        int w = vz[i][k].X;
                        for(int j=W;j>=w;--j){
                            int v = vz[i][k].Y;
                            dp[i][j] = max(dp[i][j],max(dp[i][j-w]+v,
                                        dp[i-1][j-w]+v));
                        }
                    }
                }
            }
            printf("%d
    ",max(dp[n][W],-1));
        }
        return 0;
    }
    
    
  • 相关阅读:
    【线程退出】linux线程退出的几个函数
    Apache Doris编译安装记录
    你所不知道的java编程思想
    thinking in java知识小记(一)
    一个程序员的修炼之路
    解决linux不能使用chmod更改权限的问题
    centos6.5配置无线网络
    ubuntu16.04 server安装小记
    vim的基本使用方法
    微信之父张小龙经典演讲164页PPT:《微信背后的产品观》
  • 原文地址:https://www.cnblogs.com/xiuwenli/p/9833509.html
Copyright © 2020-2023  润新知