• 混合背包问题


    题目:https://www.acwing.com/problem/content/7/

    混合背包是一个比较简单的问题,也就是物品中既有01背包,又有完全背包,还有多重背包,这个时候的多重背包一般使用二进制拆分成01背包来做,因为用单调队列优化的话需要保证初始条件一样,也就是得先读入所有的物品,然后对多重背包进行决策,然后再做01和完全背包,这样的话略显麻烦

    先给出多重背包二进制拆分的解法

     1 #include<iostream>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<vector>
     5 using namespace std;
     6 const int N=1010;
     7 int n,m;
     8 struct node
     9 {
    10     int t;
    11     int v,w;
    12 };
    13 int f[N];
    14 int main(void)
    15 {
    16     vector<node> ve;
    17     cin>>n>>m;
    18     for(int i=1; i<=n; i++)
    19     {
    20         int v,w,s;
    21         cin>>v>>w>>s;
    22         if(s==-1)
    23         {
    24             ve.push_back({-1,v,w});
    25         }
    26         else if(s==0)
    27         {
    28             ve.push_back({0,v,w});
    29         }
    30         else//二进制拆分
    31         {
    32             for(int i=1;i<=s;i*=2)
    33             {
    34                 s-=i;
    35                 ve.push_back({-1,v*i,w*i});
    36             }
    37             if(s)
    38             ve.push_back({-1,v*s,w*s});
    39         }
    40     }
    41     for(auto x:ve)
    42     {
    43         if(x.t==-1)   //01背包
    44         {
    45             for(int i=m;i>=x.v;i--)
    46             {
    47                 f[i]=max(f[i],f[i-x.v]+x.w);
    48             }
    49         }
    50         else        //完全背包
    51         {
    52             for(int i=0;i<=m;i++)
    53             {
    54                 if(i-x.v>=0)
    55                 {
    56                     f[i]=max(f[i],f[i-x.v]+x.w);
    57                 }
    58             }
    59         }
    60     }
    61     cout<<f[m];
    62     return 0;
    63 }

    下面写一下用单调队列优化多重背包,读入数据时可能有点复杂

     1 #include<iostream>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<vector>
     5 using namespace std;
     6 const int N=1010;
     7 int n,m;
     8 struct node
     9 {
    10     int s;
    11     int v,w;
    12 };
    13 struct ooo
    14 {
    15     int id;
    16     int v;
    17 };
    18 int f[N];
    19 ooo qu[N];
    20 int main(void)
    21 {
    22     vector<node> ve;
    23     vector<node> dc;
    24     cin>>n>>m;
    25     for(int i=1; i<=n; i++)
    26     {
    27         int v,w,s;
    28         cin>>v>>w>>s;
    29         if(s==-1)
    30         {
    31             ve.push_back({-1,v,w});
    32         }
    33         else if(s==0)
    34         {
    35             ve.push_back({0,v,w});
    36         }
    37         else
    38         {
    39             dc.push_back({s,v,w});
    40         }
    41     }
    42     //多重背包
    43     for(auto x:dc)//枚举物品
    44     {
    45         int num=min(x.s,m/x.v);//窗口大小
    46         for(int mod=0;mod<x.v;mod++)//枚举余数
    47         {
    48             int head=0,tail=-1;//定义队列指针
    49             for(int k=0;k<=(m-mod)/x.v;k++)//枚举决策
    50             {
    51                 int z=k,y=f[k*x.v+mod]-k*x.w;//y得减去必然增加的k*x.w,这样的话就能算出同一起跑线的最大值
    52                 if(tail<head)
    53                 {
    54                     qu[++tail]={z,y};
    55                 }
    56                 else
    57                 {
    58                     while(tail>=head&&qu[head].id<k-num)head++;//两个出队操作
    59                     while(tail>=head&&qu[tail].v<=y)tail--;
    60                     qu[++tail]={z,y};//插入队尾
    61                 }
    62                 f[k*x.v+mod]=qu[head].v+k*x.w;//更新结果
    63             }
    64         }
    65     }
    66     //01和完全背包
    67     for(auto x:ve)
    68     {
    69         if(x.s==-1)
    70         {
    71             for(int i=m;i>=x.v;i--)
    72             {
    73                 f[i]=max(f[i],f[i-x.v]+x.w);
    74             }
    75         }
    76         else
    77         {
    78             for(int i=0;i<=m;i++)
    79             {
    80                 if(i-x.v>=0)
    81                 {
    82                     f[i]=max(f[i],f[i-x.v]+x.w);
    83                 }
    84             }
    85         }
    86     }
    87     cout<<f[m];
    88     return 0;
    89 }
  • 相关阅读:
    iOS 中的类属性
    Ubuntu18.04 设置开机进入命令行模式
    ReactNative——如何隐藏状态栏(实现沉浸式)
    React Native(简单精致的底部导航栏):使用react-native-tab-navigator实现底部导航栏
    windows scp 报错 no such file or dictionary
    JS中Logger的使用
    react CSSTransition 参数
    Javaweb中的定时器
    windows配置java环境变量,修改java版本后不生效
    Eclipse中import javax.servlet.*出错
  • 原文地址:https://www.cnblogs.com/greenofyu/p/11707016.html
Copyright © 2020-2023  润新知