ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

dp_背包之多重背包

2022-05-19 19:00:34  阅读:169  来源: 互联网

标签:NMAX 多重 背包 int xx 物品 dp


问题:

多重背包也是 0-1 背包的一个变式。与 0-1 背包的区别在于每种物品有ki个,而非一个。

解决方案:

将k个相同的物品,看作k个不同的物品,但是wi,ci都一样。即可套用 01背包方案 详见(https://www.cnblogs.com/kingbuffalo/p/16241927.html)

优化方法:

  1. 二进制优化
    设k个物品分成 A[xx] A[xx+1] ... A[xx+k-1] 个物品。
    那么 A[xx] A[xx+1] 组成两个物品时 与 A[xx+1] A[xx+2] 是相同的,所以存在重复计算。
    所以,不能简单地将其看成k个不同的物品。
    而是考虑二进制 比如将 8 = 1 + 2 + 3 + 1 4个物品,分别为1个的时候,2个的时候,4个的时候,和1个的时候。(这是因为二进制 刚好就是可以表示一切数字,且某位存不存在-->即加不加上)

poj1014的 参考代码如下

#define NMAX 120003

bool dp[NMAX];
int B[10];
int A[1000];


int main(){
	ios::sync_with_stdio(false);
    cin.tie(0);

    int t = 0;
    while(cin >> B[1] >> B[2] >> B[3] >> B[4] >> B[5] >> B[6] ){
    	t ++;
    	int M = B[1] + B[2]*2 + B[3]*3 + B[4]*4 + B[5]*5 +B[6]*6;
    	if ( M == 0 ) break;
    	if ( M & 1 ){
    		cout << "Collection #"<<t <<":\nCan't be divided.\n" << endl;
    	}else{
    		M/=2;
    		int AIdx = 0;
    		for(int i=1;i<=6;i++){
    			int k = B[i];
    			if ( k == 0 ) continue;
          		int j=1;
	    		while(k>=j)A[AIdx++]=j*i,k-=j,j*=2;
	    		if(k)A[AIdx++] = k*i;
    		}
    		memset(dp,0,sizeof(dp));
	    	dp[0] = true;
    		for(int i=0;i<AIdx;++i){
    			for(int j=M;j>=A[i];j--){
    				dp[j] |= dp[j-A[i]];
    			}
    		}
	    	if ( dp[M] ) cout << "Collection #"<<t <<":\nCan be divided.\n" << endl;
	    	else cout << "Collection #"<<t <<":\nCan't be divided.\n" << endl;
    	}
    }
    return 0;
}
  1. 还有一种方法,我不知道这个叫什么方法了
#define NMAX 120003

bool dp[NMAX];
int cnts[NMAX];
int B[10];

int main(){
	ios::sync_with_stdio(false);
    cin.tie(0);

    int t = 0;
    while(cin >> B[1] >> B[2] >> B[3] >> B[4] >> B[5] >> B[6] ){
    	t ++;
    	int M = B[1] + B[2]*2 + B[3]*3 + B[4]*4 + B[5]*5 +B[6]*6;
    	if ( M == 0 ) break;
    	if ( M & 1 ){
    		cout << "Collection #"<<t <<":\nCan't be divided.\n" << endl;
    	}else{
    		M/=2;
    		memset(dp,0,sizeof(dp));
	    	dp[0] = true;
	    	for(int i=1;i<=6;++i){
	    		memset(cnts,0,sizeof(cnts));
	    		for(int j=i;j<=M;j++){
	    			if ( !dp[j] && dp[j-i] && cnts[j-i] < B[i]){
	    				dp[j] = true;
	    				cnts[j] = cnts[j-i]+1;
	    			}
	    		}
	    	}
	    	if ( dp[M] ) cout << "Collection #"<<t <<":\nCan be divided.\n" << endl;
	    	else cout << "Collection #"<<t <<":\nCan't be divided.\n" << endl;
    	}
    }

	return 0;
}

标签:NMAX,多重,背包,int,xx,物品,dp
来源: https://www.cnblogs.com/kingbuffalo/p/16285929.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有