Educational Codeforces Round 61 (Rated for Div. 2) E 多重背包优化

https://codeforces.com/contest/1132/problem/E

题意

有8种物品,重量是1~8,每种数量是\(cnt[i]\)(1e16),问容量为W(1e18)的背包最多能装多少重量

题解1

  • 多重背包二进制拆分物品转换成01背包,用map来剪枝掉无用的状态
#include<bits/stdc++.h>
#define ll long long 
using namespace std;
map<ll,bool>f,g;
ll a[10],W,s[1005],ans;
vector<ll>w;

int main(){
    cin>>W;
    for(ll i=1;i<=8;i++){
        cin>>a[i];
        if(a[i]){
            ans=max(ans,min(W/i,a[i])*i);
            ll num=1;
            while(a[i]>0){
                w.push_back(min(num,a[i])*i);
                a[i]-=min(num,a[i]);
                num*=2;
            }
        }
    }
    sort(w.begin(),w.end());
    reverse(w.begin(),w.end());
    for(int i=w.size()-1;i>=0;i--)s[i]=s[i+1]+w[i];
    f[0]=true;
    for(int i=0;i<w.size();i++){
        g.clear();
        for(map<ll,bool>::iterator it=f.begin();it!=f.end();it++){
            ll x=it->first;
            g[x]=true;
            if(x+w[i]<=W)g[x+w[i]]=true;
        }
        f.clear();
        for(map<ll,bool>::iterator it=g.begin();it!=g.end();it++){
            ll x=it->first;
            if(x+s[i]<ans)continue;
            f[x]=true;
            ans=max(ans,x);
        }
    }
    cout<<ans;
}

题解2

参考:https://blog.csdn.net/qq_37451344/article/details/88860699

  • 设1到8的最小公倍数为lcm,则将lcm/V[i]看成一整份,然后枚举0到lcm/V[i]作为第二维
#include<bits/stdc++.h>
#define ll long long 
using namespace std;
const ll lcm=840;
ll W,a[10],V[10],dp[10][10005],ans;
int main(){
    cin>>W;
    for(int i=0;i<8;i++){
        cin>>a[i];
        V[i]=i+1;
    }
    memset(dp,-1,sizeof(dp));
    dp[0][0]=0;
    for(int i=0;i<8;i++){
        ll num=lcm/V[i];
        ll end=min(num,a[i]);
        for(int j=0;j<=lcm*8;j++){
            if(dp[i][j]<0)continue;
            for(int k=0;k<=end;k++){
                if(j+k*V[i]<=lcm*8)dp[i+1][j+k*V[i]]=max(dp[i+1][j+k*V[i]],
                        dp[i][j]+(a[i]-k)/num);
            }
        }
    }
    for(int i=0;i<=lcm*8;i++){
        if(i>W)break;
        if(dp[8][i]<0)continue;
        ans=max(ans,i+lcm*min(dp[8][i],(W-i)/lcm));
    }
    cout<<ans;
}

猜你喜欢

转载自www.cnblogs.com/VIrtu0s0/p/10809622.html