Monotonic queue optimization of multiple knapsacks

Topic portal

When solving multiple knapsacks, our simplest method is to treat all items as independent and solve the 01 knapsack. The time complexity is O (NV ∑ K) O(NV\sum K)O ( N VK ) , then we can use binary optimization, the time complexity isO (NV log ∑ k) O(NVlog\sum k)O ( N V l o gk ) , but we still can't get through some problems. At this time, we need to use monotonic queues to optimize.

We first consider the ordinary state transition equation: f [i] [j] = max (f [i − 1] [j − k ∗ w] + k ∗ v), (j − k ∗ w> = 0) f[ i][j]=max(f[i-1][jk*w]+k*v),(jk*w>=0)f[i][j]=max(f[i1][jkw]+kv ) ,(jkw>=0 )
Then we can consider adjusting the loop to optimize the one-dimensional array, that is, to ensure that each time is transformed from the previous time.
Obtain the equationf [j] = max (pre [j − k ∗ w] + k ∗ v), (j − k ∗ w> = 0) f[j]=max(pre[jk*w]+k*v ),(jk*w>=0)f[j]=max(pre[jkw]+kv ) ,(jkw>=0)

Then we find that f [j] f[j]f [ j ] can only be determined bypre [j − k ∗ w] pre[jk*w]p r e [ jkw ] transformed.
We putf [m] f[m]f [ m ] (m is the total capacity of the backpack) grouping:
Insert picture description here
what we need to get ismax (pre [j − k ∗ w] + k ∗ v) max(pre[jk*w]+k*v)max(pre[jkw]+kv ) , so we maintain amax (pre [j − k ∗ w] + k ∗ v) max(pre[jk*w]+k*v)max(pre[jkw]+kThe maximum value of v ) .
Then we can get:
Insert picture description here
we find that for f[j+k*v], k is incremented by 1 each time, and w is required to be added to the value of each subsequent item, so we need to do some conversion.
Insert picture description here
Code:

#include<bits/stdc++.h>
#define endl '\n'
#define null NULL
#define ls p<<1
#define rs p<<1|1
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define ll long long
//#define int long long
#define pii pair<int,int>
#define ull unsigned long long
#define pdd pair<double,double>
#define lowbit(x) x&-x
#define all(x) (x).begin(),(x).end()
#define sz(x) (int)(x).size()
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
char *fs,*ft,buf[1<<20];
#define gc() (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<20,stdin),fs==ft))?0:*fs++;
inline int read()
{
    
    
    int x=0,f=1;
    char ch=gc();
    while(ch<'0'||ch>'9')
    {
    
    
        if(ch=='-')
            f=-1;
        ch=gc();
    }
    while(ch>='0'&&ch<='9')
    {
    
    
        x=x*10+ch-'0';
        ch=gc();
    }
    return x*f;
}
using namespace std;
const int N=2e4+55;
const int inf=0x3f3f3f3f;
const int mod=998244353;
const double eps=1e-6;
const double PI=acos(-1);
int q[N],f[N],pre[N];
void solve()
{
    
    
    int n,m;
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
    
    
        int v,w,s;
        cin>>v>>w>>s;
        memcpy(pre,f,sizeof f);
        for(int j=0;j<v;j++)
        {
    
    
            int head=0,tail=-1;
            for(int k=j;k<=m;k+=v)
            {
    
    
                if(head<=tail&&(k-q[head])/v>s)
                    head++;
                if(head<=tail)
                    f[k]=max(f[k],pre[q[head]]+(k-q[head])/v*w);
                while(head<=tail&&pre[q[tail]]-(q[tail]-j)/v*w<=pre[k]-(k-j)/v*w)
                    tail--;
                q[++tail]=k;
            }
        }
    }
    cout<<f[m]<<endl;
}
signed main()
{
    
    
//    int t;
//    cin>>t;
//    while(t--)
    solve();
    return 0;
}


Guess you like

Origin blog.csdn.net/Joker_He/article/details/109498686