HDU - 3535 AreYouBusy (分组背包)

题意

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\n",max(dp[n][W],-1));
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/xiuwenli/p/9833509.html
今日推荐