相信大家都能看出这是多重背包

但问题是怎么去掉某个玩偶

去掉玩偶就可以单独求前面的和后面的,只需要一正一反两个背包就好了,剩下就是正常的多重背包。

AC代码

#include <bits/stdc++.h>
using namespace std;

int fl[100010][1010],fr[100010][1010];//正反背包
int v[100010],w[100010],cnt,l[1010],r[1010];

int main(){
    int n,a,b,c,q,d,e,maxx;
    cin >> n;
    for(int i = 1;i <= n;i++){
        cin >> a >> b >> c;
        l[i] = cnt;
        //按1 2 4 8...拆成01背包
        int sum = 1;
        while(c>sum){
            cnt++;
            w[cnt] = a*sum,v[cnt] = b*sum;
            c-=sum;
            sum<<=1;
        }
        cnt++;
        w[cnt] = a*c,v[cnt] = b*c;
        r[i] = cnt+1;
    }
  //正一遍
    for(int i = 1;i <= cnt;i++){
        for(int j = 1;j <= 1000;j++){
            if(j<w[i]) fl[i][j] = fl[i-1][j];
            else fl[i][j] = max(fl[i-1][j],fl[i-1][j-w[i]]+v[i]);
        }
    }
  //反一遍
    for(int i = cnt;i >= 1;i--){
        for(int j = 1;j <= 1000;j++){
            if(j<w[i]) fr[i][j] = fr[i+1][j];
            else fr[i][j] = max(fr[i+1][j],fr[i+1][j-w[i]]+v[i]);
        }
    }
    cin >> q;
    while(q--){
        cin >> d >> e;
        d++;
        maxx = 0;
        for(int i = 0;i <= e;i++){//分配前后容量
            maxx = max(maxx,fl[l[d]][i]+fr[r[d]][e-i]);
        }
        cout << maxx << endl;
    }
    return 0;
}