hdu_3535 (AreYouBusy)

Posted shanyr

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu_3535 (AreYouBusy)相关的知识,希望对你有一定的参考价值。

http://acm.hdu.edu.cn/showproblem.php?pid=3535

题意:

?????? 给你n个工作集合,给你T的时间去做它们。给你m和s,说明这个工作集合有m件事可以做,它们是s类的工作集合(s=0,1,2,s=0说明这m件事中最少得做一件,s=1说明这m件事中最多只能做一件,s=2说明这m件事你可以做也可以不做)。再给你ci和gi代表你做这件事要用ci的时间,能获得gi的快乐值。求在T的时间内你能获得的最大快乐值。

分析:

?????? 首先如果存在最优解, 我们可以互换不同工作集合的处理顺序, 依然能得到最优解. 那么我们下面只需要处理每个单独的工作集合即可.

?????? 令dp[i][j]==x表示处理完前i组工作集,所花时间<=j时的快乐值为x。每得到一组工作就进行一次DP,所以dp[i]为第i组的结果。下面对三种情况进行讨论。

? ? ???1.????该集合内至少要选1件工作时. 要保证至少选1个第i类工作, 可以从第i-1类的结果dp[i-1]来更新dp[i].也可以用? ? ? ? ? ?01背包的思想, 从本类的前一个工作更新后一个工作.

? ? ???初始化:dp[i]全为负无穷.(即-INF)

? ? ???状态转移方程为:

? ? ???dp[i][k]=max{dp[i][k],dp[i-1][k-cost[j]]+val[k],dp[i][k-cost[j]]+val[j] }

? ? ???2.????该集合内最多选1件工作时. 只能从上一层的结果dp[i-1]来更新dp[i]了.(想想为什么)

? ? ???初始化:dp[i]==dp[i-1].

? ? ???状态转移方程为dp[i][k]=max{dp[i][k],dp[i-1][k-cost[j]]+val[k]}.

? ? ???3.????该集合内工作可以随便选. 这就是1个普通的01背包问题了.

? ? ???初始化:dp[i]==dp[i-1].

? ? ???状态转移方程为:

? ? ???dp[i][k]=max{dp[i][k],dp[i-1][k-cost[j]]+val[k],dp[i][k-cost[j]]+val[j] }

?

? ? ???最终所求:dp[n][t]的值.

注意,为了防止越界,所以dp数组从1开始

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

#define INF 1e8
int dp[110][110];
int w[110];
int v[110];
int main()
{
    int n,V;
    while(~scanf("%d%d",&n,&V)){
        int m,t,cnt;
        memset(dp,0,sizeof(dp));
        for(int i = 1; i <= n ;i++){
            scanf("%d%d",&m,&t);
            for(int j = 0; j < m; j++){
                scanf("%d%d",&w[j],&v[j]);
                if(t==0){
                    if(j==0){
                        for(int k = 0; k <= V; k++) dp[i][k] = -INF;
                    }
                    for(int k = V; k >= w[j]; k--){
                        //dp[i][k] = max(dp[i][k],max(dp[i-1][k-w[j]]+v[j],dp[i][k-w[j]]+v[j]));
                        //下面两个方程不能换,因为有可能 w = 0的时候换了有可能会被加两次。
                        dp[i][k] = max(dp[i][k],dp[i][k-w[j]]+v[j]);
                        dp[i][k] = max(dp[i][k],dp[i-1][k-w[j]]+v[j]);
                    }
                }
                else if(t==2){
                    if(j==0){
                        for(int k = 0; k <= V; k++) dp[i][k] = dp[i-1][k];
                    }
                    for(int k = V; k >= w[j]; k--){
                        dp[i][k] = max(dp[i][k],dp[i][k-w[j]]+v[j]);
                    }
                }
                else{
                    if(j==0){
                        for(int k = 0; k <= V; k++) dp[i][k] = dp[i-1][k];
                    }
                    for(int k = V; k >= w[j]; k--){
                        dp[i][k] = max(dp[i][k],dp[i-1][k-w[j]]+v[j]);
                    }
                }

                cnt++;
            }
        }
        printf("%d
",max(dp[n][V],-1));
    }
    return 0;
}

以上是关于hdu_3535 (AreYouBusy)的主要内容,如果未能解决你的问题,请参考以下文章

HDU3535AreYouBusy[混合背包 分组背包]

HDU 3535 AreYouBusy (混合背包)

HDU - 3535:AreYouBusy (分组背包)

hdu 3535 (最少1,最多1,任意)(背包混合)(好题)

hdu3535 背包大杂汇

HDU 3535 分组混合背包