多重背包转换成0-1背包

2024-09-09 08:32
文章标签 背包 转换成 多重

本文主要是介绍多重背包转换成0-1背包,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

http://acm.hdu.edu.cn/showproblem.php?pid=2191

多重背包特点:
一种物品有C个(既不是固定的1个,也不是无数个)

优化的方法:
运用神奇的二进制,进行物品拆分,转化成01背包
物品拆分,把13个相同的物品分成4组(1,2,4,6)
用这4组可以组成任意一个1~13之间的数!
原理:一个数总可以用2^k表示
而且总和等于13,所以不会组成超过13的数

所以可将一种有C个的物品拆分成1,2,4,...,2^(k-1),C-(2^k-1)
然后进行01背包
const  int  Max_N = 1008 ;int  N , V ;
int  dp[Max_N] , w[Max_N] , v[Max_N] ;void Dvide(int _v , int  _w , int S){int x = 1 ;while(S >= x){w[++N] = _w * x ;v[N] = _v * x ;S -= x ;x <<= 1 ;}if(S != 0){w[++N] = _w * S ;v[N] = _v * S ;}
}int  main(){int T  , M , i  , j  , _w , _v , _s;cin>>T ;while(T--){cin>>V>>M ;N = 0 ;memset(dp , 0 , sizeof(dp)) ;while(M--){scanf("%d%d%d" , &_v , &_w , &_s) ;Dvide(_v , _w , _s) ;}for(i = 1 ; i <= N ; i++){for(j = V ; j >= v[i] ; j--){dp[j] = max(dp[j] , dp[j-v[i]] + w[i]) ;}}printf("%d\n" , dp[V]) ;}return 0 ;
}


http://acm.hdu.edu.cn/showproblem.php?pid=1059

1 , 2 , 3 ,4 ,5 ,6  有x1 , x2 ,x3 ,x4 ,x5 ,x6个 ,问能否平分成2份和相等。

const int Max_N = 6 * 400 ;int N ;
int v[Max_N] ;void Divide(int _v , int S){int x = 1 ;while(S >= x){v[++N] =  x * _v ;S -= x ;x <<= 1 ;}if(S > 0){v[++N] = S * _v ;}
}int x[7] ;
bool dp[210008] ;int main(){int sum , k = 1  , i , j ;while(scanf("%d" ,&x[1])){sum = x[1] ;for(i = 2 ; i <= 6 ; i++){scanf("%d" ,&x[i]) ;sum += i*x[i] ;}if(sum == 0)  break ;printf("Collection #%d:\n" , k++) ;if(sum & 1){puts("Can't be divided.") ;puts("") ;continue ;}sum >>= 1 ;N = 0 ;fill(dp , dp+sum+1 , 0) ;dp[0] = 1 ;for(i = 1 ; i <= 6 ; i++)Divide(i , x[i]) ;for(i = 1 ; i <= N ; i++){for(j = sum ; j >= v[i] ; j--){dp[j] |= dp[j-v[i]] ;}}printf("%s\n" , dp[sum]? "Can be divided." : "Can't be divided.") ;puts("") ;}return 0 ;
}


http://acm.hdu.edu.cn/showproblem.php?pid=2844

多重背包问题,用n个物品,每个物品有价值v[i],每个物品数量限制为c[i]

这道题是问,用所有的硬币能够在m的范围内最多可以组合成多少种价值


对于每个硬币而言:

 

IF 价值×数量>=V

       THEN 取这个硬币的次数相当于无限制,可以考虑成完全背包

ELSE

       THEN 考虑成0-1背包(二进制优化)

const int Max_N =  100008 ;
const int Max_M =  108 ;int  v[Max_N] , c[Max_N] ;
int  dp[Max_N] ;
int  V , N ;void  ZoreOnePack(int v , int w){for(int i = V ; i >= v ; i--)dp[i] = max(dp[i] , dp[i - v] + w) ;
}void  CompletePack(int v , int w){for(int i = v ; i <= V ; i++)dp[i] = max(dp[i] , dp[i - v] + w) ;
}int  DP(){int x , i  , ans = 0  ;fill(dp , dp+1+V , 0) ;for(i = 1 ; i <= N ; i++){if(v[i] * c[i] >= V)CompletePack(v[i] , v[i]) ;else{x = 1  ;while(c[i] >= x){ZoreOnePack(v[i]*x , v[i]*x) ;c[i] -= x ;x <<= 1 ;}if(c[i] > 0)ZoreOnePack(v[i]*c[i] , v[i]*c[i]) ;}}for(i = 1 ; i <= V ; i++)ans += dp[i] == i  ;return ans ;
}int  main(){int i ;while(cin>>N>>V){if(N == 0 && V == 0)  break ;for(i = 1 ; i <= N ; i++)scanf("%d" ,&v[i])   ;for(i = 1 ; i <= N ; i++)scanf("%d" ,&c[i])  ;if(V <= 0)puts("0") ;elsecout<<DP()<<endl ;}return 0 ;
}








这篇关于多重背包转换成0-1背包的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1150647

相关文章

poj2576(二维背包)

题意:n个人分成两组,两组人数只差小于1 , 并且体重只差最小 对于人数要求恰好装满,对于体重要求尽量多,一开始没做出来,看了下解题,按照自己的感觉写,然后a了 状态转移方程:dp[i][j] = max(dp[i][j],dp[i-1][j-c[k]]+c[k]);其中i表示人数,j表示背包容量,k表示输入的体重的 代码如下: #include<iostream>#include<

hdu2159(二维背包)

这是我的第一道二维背包题,没想到自己一下子就A了,但是代码写的比较乱,下面的代码是我有重新修改的 状态转移:dp[i][j] = max(dp[i][j], dp[i-1][j-c[z]]+v[z]); 其中dp[i][j]表示,打了i个怪物,消耗j的耐力值,所得到的最大经验值 代码如下: #include<iostream>#include<algorithm>#include<

csu(背包的变形题)

题目链接 这是一道背包的变形题目。好题呀 题意:给n个怪物,m个人,每个人的魔法消耗和魔法伤害不同,求打死所有怪物所需的魔法 #include<iostream>#include<algorithm>#include<cstring>#include<stack>#include<queue>#include<set>//#include<u>#include<map

hdu1011(背包树形DP)

没有完全理解这题, m个人,攻打一个map,map的入口是1,在攻打某个结点之前要先攻打其他一个结点 dp[i][j]表示m个人攻打以第i个结点为根节点的子树得到的最优解 状态转移dp[i][ j ] = max(dp[i][j], dp[i][k]+dp[t][j-k]),其中t是i结点的子节点 代码如下: #include<iostream>#include<algorithm

hdu1171(母函数或多重背包)

题意:把物品分成两份,使得价值最接近 可以用背包,或者是母函数来解,母函数(1 + x^v+x^2v+.....+x^num*v)(1 + x^v+x^2v+.....+x^num*v)(1 + x^v+x^2v+.....+x^num*v) 其中指数为价值,每一项的数目为(该物品数+1)个 代码如下: #include<iostream>#include<algorithm>

webm怎么转换成mp4?这几种方法超多人在用!

webm怎么转换成mp4?WebM作为一种新兴的视频编码格式,近年来逐渐进入大众视野,其背后承载着诸多优势,但同时也伴随着不容忽视的局限性,首要挑战在于其兼容性边界,尽管WebM已广泛适应于众多网站与软件平台,但在特定应用环境或老旧设备上,其兼容难题依旧凸显,为用户体验带来不便,再者,WebM格式的非普适性也体现在编辑流程上,由于它并非行业内的通用标准,编辑过程中可能会遭遇格式不兼容的障碍,导致操

hdu 2602 and poj 3624(01背包)

01背包的模板题。 hdu2602代码: #include<stdio.h>#include<string.h>const int MaxN = 1001;int max(int a, int b){return a > b ? a : b;}int w[MaxN];int v[MaxN];int dp[MaxN];int main(){int T;int N, V;s

uva 10130 简单背包

题意: 背包和 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#include <stack>#include <vector>#include <queue>#include <map>

HDU 2159 二维完全背包

FATE 最近xhd正在玩一款叫做FATE的游戏,为了得到极品装备,xhd在不停的杀怪做任务。久而久之xhd开始对杀怪产生的厌恶感,但又不得不通过杀怪来升完这最后一级。现在的问题是,xhd升掉最后一级还需n的经验值,xhd还留有m的忍耐度,每杀一个怪xhd会得到相应的经验,并减掉相应的忍耐度。当忍耐度降到0或者0以下时,xhd就不会玩这游戏。xhd还说了他最多只杀s只怪。请问他能

POJ1384背包

体积V的包包 n种硬币,体积weight价值value 求把包包恰好装满最小的价值 import java.io.BufferedReader;import java.io.InputStream;import java.io.InputStreamReader;import java.io.PrintWriter;import java.math.BigInteger;imp