动态规划【4】之混合背包

混合背包就是将前面三种的背包问题混合起来,有的只能取一次,有的能取无限次,有的只能取 k k 次。1

例题:luogu1833 樱花

事实上,我们直接对不同的物品按情况讨论即可。
关于混合背包,0/1背包可以看成是多重背包的特例( k = 1 k=1 ),因此,仅考虑两种情况即可。

luogu1833 樱花对应的代码如下:

/* ***********************************************
Author        : VFVrPQ
Created Time  : 五  2/28 15:39:08 2020
File Name     : luogu1833樱花.cpp
Problem       : 
Description   : 
Solution      : 
Tag           : 
************************************************ */

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <cmath>
#include <cstdlib>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <iomanip>
using namespace std;
#define DEBUG(x) cout<<x<<endl;
const int N = 1e4+10;
const int M = 1e9+7;
const int INF = 1e9+7;

string ts, te;
int n;
int t[N],c[N],p[N];
int dp[N];

int getStr(string t){
    int i;
    int ret = 0;
    for (i=0;t[i]!='\0';i++){
        if (t[i]==':') break;
        ret = ret * 10 + t[i]-'0';
    }
    ret*=60; //转换成分钟
    int now = 0;
    for (i+=1;t[i]!='\0';i++){
        now = now * 10 + t[i]-'0';
    }
    return ret+now;
}
int main()
{
    cin >> ts >> te >> n;
    for (int i=1;i<=n;i++){
        cin >> t[i] >> c[i] >> p[i];
    }
    int maxT = getStr(te) - getStr(ts);
    
    for (int i=1;i<=n;i++){
        if (p[i] == 0){//完全背包
            for (int j=t[i];j<=maxT;j++) dp[j] = max(dp[j], dp[j-t[i]]+c[i]);
        }else {//多重背包
            for (int k=1;;k*=2){
                int now = k;//当前的物品个数
                if (now >= p[i]) now = p[i];//取较小者

                for (int j=maxT;j>=now*t[i];j--) dp[j] = max(dp[j], dp[j-now*t[i]]+now*c[i]);//now*的0/1背包
                p[i] -= now;
                if (p[i]==0) break;
            }
        }
    }
    printf("%d\n",dp[maxT]);
    //for (int i=0;i<=maxT;i++) printf("%d ",dp[i]);
    //printf("%d\n",maxT);
    return 0;
}

  1. https://oi-wiki.org/dp/knapsack/#_5 ↩︎

发布了74 篇原创文章 · 获赞 30 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/MustImproved/article/details/104558326
今日推荐