zoukankan      html  css  js  c++  java
  • 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;
    }
    
    
  • 相关阅读:
    ffmpeg rtmp推流 视频转码
    java日志发展史 log4j slf4j log4j2 jul jcl 日志和各种桥接包的关系
    nginx stream 流转发,可以转发rtmp、mysql访问流,转发rtmp、jdbc请求
    java web http 转https 通过nginx代理访问
    linux 服务器磁盘挂载
    novnc 通过websockify代理 配置多点访问
    linux 文件服务 minio 安装部署配置
    AOP实现原理,手写aop
    java 泛型
    JAVA反射getGenericSuperclass()用法
  • 原文地址:https://www.cnblogs.com/shanyr/p/11862639.html
Copyright © 2011-2022 走看看