zoukankan      html  css  js  c++  java
  • UESTC 424 AreYouBusy --混合背包

    混合三种背包问题。

    定义:dp[i][k]表示体积为k的时候,在前i堆里拿到的最大价值。

    第一类,至少选一项,dp初值全赋为负无穷,这样才能保证不会出现都不选的情况。
    dp[i][k] = max(dp[i][k],max(dp[i-1][k-c]+g,dp[i][k-c]))
    其中:

    dp[i][k]是不选当前项
    dp[i-1][k-c]+g是表示第一次选这组的物品
    dp[i][k-c]+g表示选择当前物品,并且不是第一次选。

    第二类最多选一个,一旦选则是第一次选
    dp[i][k] = max(dp[i][k],dp[i-1][k-c]+g);
    注意全局最优解,需复制上一组解到这一组。

    第三类,无限制,则跑一个01背包
    dp[i][k] = max(dp[i][k],dp[i][k-c]+g)
    注意仍需复制上一组解。

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    using namespace std;
    #define N 10007
    
    int dp[N][107];
    int c,g;
    
    int Max(int k1,int k2,int k3)
    {
        return max(max(k1,k2),k3);
    }
    
    int main()
    {
        int n,T,i,j,k;
        int m,s,set;
        while(scanf("%d%d",&n,&T)!=EOF)
        {
            for(i=1;i<=n;i++)
            {
                scanf("%d%d",&m,&s);
                if(s == 0)    //至少选一项
                {
                    for(j=0;j<=T;j++)
                        dp[i][j] = -Mod;
                    for(j=0;j<m;j++)
                    {
                        scanf("%d%d",&c,&g);
                        for(k=T;k>=0;k--)
                        {
                            int t1 = dp[i][k];  //不选择此工作
                            int t2 = -Mod;
                            int t3 = -Mod;
                            if(k >= c)
                            {
                                t2 = dp[i-1][k-c] + g;  //第一次选此工作
                                t3 = dp[i][k-c] + g;   //选择并且不是第一次选
                            }
                            dp[i][k] = Max(t1,t2,t3);
                        }
                    }
                }
                else if(s == 1)  //最多选一项
                {
                    for(j=0;j<=T;j++)
                        dp[i][j] = dp[i-1][j];  //由上一堆推来
                    for(j=0;j<m;j++)
                    {
                        scanf("%d%d",&c,&g);
                        for(k=T;k>=0;k--)
                        {
                            int t1 = dp[i][k];
                            int t2 = -Mod;
                            if(k >= c)
                                t2 = dp[i-1][k-c] + g;
                            dp[i][k] = max(t1,t2);
                        }
                    }
                }
                else if(s == 2)    //随便选
                {
                    for(j=0;j<=T;j++)
                        dp[i][j] = dp[i-1][j];
                    for(j=0;j<m;j++)
                    {
                        scanf("%d%d",&c,&g);
                        for(k=T;k>=c;k--)
                        {
                            dp[i][k] = max(dp[i][k],dp[i][k-c]+g);
                        }
                    }
                }
            }
            printf("%d
    ",max(dp[n][T],-1));
        }
        return 0;
    }
    View Code
  • 相关阅读:
    方法
    顺序结构 基本语句
    包,Doc
    运算符
    变量
    类型转换
    day7——JAVA数组
    day6——java方法
    day5——java流程控制
    day4
  • 原文地址:https://www.cnblogs.com/whatbeg/p/3762760.html
Copyright © 2011-2022 走看看