[学习笔记] 浅谈多重背包二进制优化


做题的时候看到一种写多重背包二进制优化的好方法,特地记录一下

之前写的方法既难理解又难记,而且这个还跑得快(


\(num\) 件物品,价值 \(val\) ,花费 \(cost\) 的物品拆分为

\((v,w),(v\times2^1,w\times 2^1),(v\times2^2,w\times 2^2),(v\times2^3,w\times 2^3)...(x,y)\) 最后的是无法被拆的余项

如此便可通过这些 \(\log_{2}num\) 件的物品凑成所有可能的取值状态

与之前写法的不同之处就是先预处理出来了物品数量,也能更加直观地看到“把一些物品合成一个物品”这一思想

#include 
using namespace std;
const int N=1e5+10;
int dp[N],w[N],v[N],n,m,cnt;
inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    return x*f;
}
int main(){
    n=read();m=read();
    for(int i=1;i<=n;++i){
	int val=read(),wast=read(),num=read();
	for(int j=1;j<=num;j<<=1){
	    v[++cnt]=val*j;
	    w[cnt]=wast*j;
	    num-=j;
	}
	if(num) v[++cnt]=num*val,w[cnt]=num*wast;
    }
    for(int i=1;i<=cnt;++i)
	for(int j=m;j>=w[i];j--)
	    dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
    printf("%d",dp[m]);
    return 0;
}

\(from:\)

相关