背包问题回溯法背包问题伪多项式算法是什么意思

背包问题回溯法  时间:2021-09-13  阅读:()

背包问题的算法

1)登上算法 用登山算法求解背包问题 function []=DengShan(n,G,P,W) %n是背包的个数,G是背包的总容量,P是价值向量,W是物体的重量向量 %n=3;G=20;P=[25,24,15];W2=[18,15,10];%输入量 W2=W; [Y,I]=sort(-P./W2);W1=[];X=[];X1=[]; for i=1:length(I) W1(i)=W2(I(i)); end W=W1; for i=1:n X(i)=0; RES=G;%背包的剩余容量 j=1; while W(j)<=RES X(j)=1; RES=RES-W(j); j=j+1; end X(j)=RES/W(j); end for i=1:length(I) X1(I(i))=X(i); end X=X1; disp('装包的方法是');disp(X);disp(X.*W2);disp('总的价值是:');disp(P*X'); 时间复杂度是非指数的 2)递归法 先看完全背包问题 一个旅行者有一个最多能用m公斤的背包,现在有n种物品,每件的重量分别是W1,W2,...,Wn, 每件的价值分别为C1,C2,...,Cn.若的每种物品的件数足够多. 求旅行者能获得的最大总价值。

本问题的数学模型如下: 设 f(x)表示重量不超过x公斤的最大价值, 则 f(x)=max{f(x-i)+c[i]} 当x>=w[i] 1<=i<=n 可使用递归法解决问题程序如下: program knapsack04; const maxm=200;maxn=30; type ar=array[0..maxn] of integer; var m,n,j,i,t:integer; c,w:ar; function f(x:integer):integer; var i,t,m:integer; begin if x=0 then f:=0 else begin t:=-1; for i:=1 to n do begin if x>=w[i] then m:=f(x-i)+c[i]; if m>t then t:=m; end; f:=t; end; end; begin readln(m,n); for i:= 1 to n do readln(w[i],c[i]); writeln(f(m)); end. 说明:当m不大时,编程很简单,但当m较大时,容易超时. 4.2 改进的递归法 改进的的递归法的思想还是以空间换时间,这只要将递归函数计算过程中的各个子函数的值保存起来,开辟一个 一维数组即可 程序如下: program knapsack04; const maxm=2000;maxn=30; type ar=array[0..maxn] of integer; var m,n,j,i,t:integer; c,w:ar; p:array[0..maxm] of integer; function f(x:integer):integer; var i,t,m:integer; begin if p[x]<>-1 then f:=p[x] else begin if x=0 then p[x]:=0 else begin t:=-1; for i:=1 to n do begin if x>=w[i] then m:=f(i-w[i])+c[i]; if m>t then t:=m; end; p[x]:=t; end; f:=p[x]; end; end; begin readln(m,n); for i:= 1 to n do readln(w[i],c[i]); fillchar(p,sizeof(p),-1); writeln(f(m)); end. 3)贪婪算法 改进的背包问题:给定一个超递增序列和一个背包的容量,然后在超递增序列中选(只能选一次)或不选每一个数值,使得选中的数值的和正好等于背包的容量。

代码思路:从最大的元素开始遍历超递增序列中的每个元素,若背包还有大于或等于当前元素值的空间,则放入,然后继续判断下一个元素;若背包剩余空间小于当前元素值,则判断下一个元素 简单模拟如下: #define K 10 #define N 10 #i nclude <stdlib.h> #i nclude <conio.h> void create(long array[],int n,int k) {/*产生超递增序列*/ int i,j; array[0]=1; for(i=1;i<n;i++) { long t=0; for(j=0;j<i;j++) t=t+array[j]; array[i]=t+random(k)+1; } } void output(long array[],int n) {/*输出当前的超递增序列*/ int i; for(i=0;i<n;i++) { if(i%5==0) printf(" "); printf("%14ld",array[i]); } } void beibao(long array[],int cankao[],long value,int count) {/*背包问题求解*/ int i; long r=value; for(i=count-1;i>=0;i--)/*遍历超递增序列中的每个元素*/ { if(r>=array[i])/*如果当前元素还可以放入背包,即背包剩余空间还大于当前元素*/ { r=r-array[i]; cankao[i]=1; } else/*背包剩余空间小于当前元素值*/ cankao[i]=0; } } void main() { long array[N]; int cankao[N]={0}; int i; long value,value1=0; clrscr(); create(array,N,K); output(array,N); printf(" Input the value of beibao: "); scanf("%ld",&value); beibao(array,cankao,value,N); for(i=0;i<N;i++)/*所有已经选中的元素之和*/ if(cankao[i]==1) value1+=array[i]; if(value==value1) { printf(" We have got a solution,that is: "); for(i=0;i<N;i++) if(cankao[i]==1) { if(i%5==0) printf(" "); printf("%13ld",array[i]); } } else printf(" Sorry.We have not got a solution. "); } 贪婪算法的另一种写法,beibao函数是以前的代码,用来比较两种算法: #define K 10 #define N 10 #i nclude <stdlib.h> #i nclude <conio.h> void create(long array[],int n,int k) { int i,j; array[0]=1; for(i=1;i<n;i++) { long t=0; for(j=0;j<i;j++) t=t+array[j]; array[i]=t+random(k)+1; } } void output(long array[],int n) { int i; for(i=0;i<n;i++) { if(i%5==0) printf(" "); printf("%14ld",array[i]); } } void beibao(long array[],int cankao[],long value,int count) { int i; long r=value; for(i=count-1;i>=0;i--) { if(r>=array[i]) { r=r-array[i]; cankao[i]=1; } else cankao[i]=0; } } int beibao1(long array[],int cankao[],long value,int n) {/*贪婪算法*/ int i; long value1=0; for(i=n-1;i>=0;i--)/*先放大的物体,再考虑小的物体*/ if((value1+array[i])<=value)/*如果当前物体可以放入*/ { cankao[i]=1;/*1表示放入*/ value1+=array[i];/*背包剩余容量减少*/ } else cankao[i]=0; if(value1==value) return 1; return 0; } void main() { long array[N]; int cankao[N]={0}; int cankao1[N]={0}; int i; long value,value1=0; clrscr(); create(array,N,K); output(array,N); printf(" Input the value of beibao: "); scanf("%ld",&value); beibao(array,cankao,value,N); for(i=0;i<N;i++) if(cankao[i]==1) value1+=array[i]; if(value==value1) { printf(" We have got a solution,that is: "); for(i=0;i<N;i++) if(cankao[i]==1) { if(i%5==0) printf(" "); printf("%13ld",array[i]); } } else printf(" Sorry.We have not got a solution. "); printf(" Second method: "); if(beibao1(array,cankao1,value,N)==1) { for(i=0;i<N;i++) if(cankao1[i]==1) { if(i%5==0) printf(" "); printf("%13ld",array[i]); } } else printf(" Sorry.We have not got a solution. "); } 4)动态规划算法 解决0/1背包问题的方法有多种,最常用的有贪婪法和动态规划法。

其中贪婪法无法得到问题的最优解,而动态规划法都可以得到最优解,下面是用动态规划法来解决0/1背包问题。

动态规划算法与分治法类似,其基本思想是将待求解问题分解成若干个子问题,然后从这些子问题的解得到原问题的解。

与分治法不同的是,适合于用动态规划法求解的问题,经分解得到的子问题往往不是互相独立的,若用分治法解这类问题,则分解得到的子问题数目太多,以至于最后解决原问题需要耗费过多的时间。

动态规划法又和贪婪算法有些一样,在动态规划中,可将一个问题的解决方案视为一系列决策的结果。

不同的是,在贪婪算法中,每采用一次贪婪准则便做出一个不可撤回的决策,而在动态规划中,还要考察每个最优决策序列中是否包含一个最优子序列。

0/1背包问题 在0 / 1背包问题中,需对容量为c 的背包进行装载。

从n 个物品中选取装入背包的物品,每件物品i 的重量为wi ,价值为pi 。

对于可行的背包装载,背包中物品的总重量不能超过背包的容量,最佳装载是指所装入的物品价值最高,即p1*x1+p2*x1+...+pi*xi(其1<=i<=n,x取0或1,取1表示选取物品i) 取得最大值。

在该问题中需要决定x1 .. xn的值。

假设按i = 1,2,...,n 的次序来确定xi 的值。

如果置x1 = 0,则问题转变为相对于其余物品(即物品2,3,.,n),背包容量仍为c 的背包问题。

若置x1 = 1,问题就变为关于最大背包容量为c-w1 的问题。

现设r?{c,c-w1 } 为剩余的背包容量。

在第一次决策之后,剩下的问题便是考虑背包容量为r 时的决策。

不管x1 是0或是1,[x2 ,.,xn ] 必须是第一次决策之后的一个最优方案,如果不是,则会有一个更好的方案[y2,.,yn ],因而[x1,y2,.,yn ]是一个更好的方案。

假设n=3, w=[100,14,10], p=[20,18,15], c= 116。

若设x1 = 1,则在本次决策之后,可用的背包容量为r= 116-100=16 。

[x2,x3 ]=[0,1] 符合容量限制的条件,所得值为1 5,但因为[x2,x3 ]= [1,0] 同样符合容量条件且所得值为1 8,因此[x2,x3 ] = [ 0,1] 并非最优策略。

即x= [ 1,0,1] 可改进为x= [ 1,1,0 ]。

若设x1 = 0,则对于剩下的两种物品而言,容量限制条件为116。

总之,如果子问题的结果[x2,x3 ]不是剩余情况下的一个最优解,则[x1,x2,x3 ]也不会是总体的最优解。

在此问题中,最优决策序列由最优决策子序列组成。

假设f (i,y) 表示剩余容量为y,剩余物品为i,i + 1,...,n 时的最优解的值,即:利用最优序列由最优子序列构成的结论,可得到f 的递归式为: 当j>=wi时: f(i,j)=max{f(i+1,j),f(i+1,j-wi)+vi} ①式 当0<=j<wi时:f(i,j)=f(i+1,j) ②式 fn( 1 ,c) 是初始时背包问题的最优解。

以本题为例:若0≤y<1 0,则f ( 3 ,y) = 0;若y≥1 0,f ( 3 ,y) = 1 5。

利用②式,可得f (2, y) = 0 ( 0≤y<10 );f(2,y)= 1 5(1 0≤y<1 4);f(2,y)= 1 8(1 4≤y<2 4)和f(2,y)= 3 3(y≥2 4)。

因此最优解f ( 1 , 11 6 ) = m a x {f(2,11 6),f(2,11 6 - w1)+ p1} = m a x {f(2,11 6),f(2,1 6)+ 2 0 } = m a x { 3 3,3 8 } = 3 8。

现在计算xi 值,步骤如下:若f ( 1 ,c) =f ( 2 ,c),则x1 = 0,否则x1 = 1。

接下来需从剩余容量c-w1中寻求最优解,用f (2, c-w1) 表示最优解。

依此类推,可得到所有的xi (i= 1.n) 值。

在该例中,可得出f ( 2 , 116 ) = 3 3≠f ( 1 , 11 6 ),所以x1 = 1。

接着利用返回值3 8 -p1=18 计算x2 及x3,此时r = 11 6 -w1 = 1 6,又由f ( 2 , 1 6 ) = 1 8,得f ( 3 , 1 6 ) = 1 4≠f ( 2 , 1 6 ),因此x2 = 1,此时r= 1 6 -w2 = 2,所以f (3,2) =0,即得x3 = 0。

0/1背包 回溯算法

#include using namespace std; struct bag{ double w; double p; double p_w; int order; }; //说明物品特性 void sort(struct bag *a,int low,int high); int main() { int n,i; double *x; //解向量,由于书数组,拿指针表示 double m,cost=0; struct bag *b; //结构数组,用于表示所有物品 //定义文件流并与具体的磁盘文件相关联 ifstream fin; fin.open("背包问题_in.txt"); ofstream fout; fout.open("背包问题_out.txt"); //输入物品数目 n 背包容量 M fin>>n>>m; //动态分配存储空间 b=new struct bag[n]; x=new double[n]; for(i=0;i>b[i].w>>b[i].p; //输入物品重量和运价 b[i].p_w=b[i].p/b[i].w; //求出运价重量比 b[i].order=i; //贴标签 } sort(b,0,n-1); //按运价重量比从大到小进行排序 for(i=0;i=t) ++low; a[high]=a[low]; } a[low]=temp; return low; } void sort(struct bag *a,int low,int high) { int loc; if(low用贪心算法解决背包问题用贪心算法解决背包问题,首先要明白,结果不一定是全局最优的。

对于贪心法而言,首先步骤是找到最优度量标准,我这里的算法采用的最优度量标准是: 收益p/重量w 的值最大者优先放入背包中,所以有算法如下:void GreedyKnapsack(float * x){ //前置条件:w[i]已按p[i]/w[i]的非增次序排列 float u=m; //u为背包剩余载重量,初始时为m for(int i=0;iu) break; x[i]=1.0; u=u-w[i]; } if(i背包问题伪多项式算法是什么意思问题描述: 给定n种物品和一背包,物品i的重量是wi,其价值为vi,背包的容量为C。

问应如何选择装入背包的物品(物品不能分割),使得装入背包中物品的总价值最大?抽象描述如下: x[n]:表示物品的选择,x[i]=1表示选择放进物品i到背包中。

问题分析: 1.抽象之后背包问题转换为找到一个最优的数组,x1,x2,..,xn的0-1序列。

2.假设最优解的序列为x1,x2,..,xn,能使背包容量C的总价值最大. 如果,x1=1,则x2,,xn是C-w1容量的背包的总价值依然是最大的序列; 如果,x1=0,则x2,.,xn是C容量的背包的总价值依然是最大的序列。

这就是我们所说的最优子结构性质。

3.进一步分析:我们用m(i,j)表示为已经判断好了1:i-1的序列的背包最大价值,并且此时的背包剩余的容量为j,对物品i进行判断 如果j>wi,就只要做出选择wi和不选择wi情况下,哪种更能使背包的总价值更大:m(i,j)=max{m(i+1,j),m(i+1,j-wi)+vi}(注意这是个递归式) 如果j=wn); m(n,j)=0 (0<=j

ZJI(月付450元),香港华为云线路服务器、E3服务器起

ZJI发布了9月份促销信息,针对香港华为云线路物理服务器华为一型提供立减300元优惠码,优惠后香港华为一型月付仅450元起。ZJI是原来Wordpress圈知名主机商家:维翔主机,成立于2011年,2018年9月更名为ZJI,提供中国香港、台湾、日本、美国独立服务器(自营/数据中心直营)租用及VDS、虚拟主机空间、域名注册等业务,商家所选数据中心均为国内访问质量高的机房和线路,比如香港阿里云、华为...

VoLLcloud(月付低至2.8刀)香港vps大带宽,三网直连

VoLLcloud LLC是一家成立于2020年12月互联网服务提供商企业,于2021年1月份投入云计算应用服务,为广大用户群体提供云服务平台,已经多个数据中心部署云计算中心,其中包括亚洲、美国、欧洲等地区,拥有自己的研发和技术服务团队。现七夕将至,VoLLcloud LLC 推出亚洲地区(香港)所有产品7折优惠,该产品为CMI线路,去程三网163,回程三网CMI线路,默认赠送 2G DDoS/C...

ZJI:香港物理服务器,2*E5-2630L/32G/480G SSD/30Mbps/2IP/香港BGP,月付520元

zji怎么样?zji是一家老牌国人主机商家,公司开办在香港,这个平台主要销售独立服务器业务,和hostkvm是同一样,两个平台销售的产品类别不一平,商家的技术非常不错,机器非常稳定。昨天收到商家的优惠推送,目前针对香港邦联四型推出了65折优惠BGP线路服务器,性价比非常不错,有需要香港独立服务器的朋友可以入手,非常适合做站。zji优惠码:月付/年付优惠码:zji 物理服务器/VDS/虚拟主机空间订...

背包问题回溯法为你推荐
容灾备份容灾备份的容灾分类网页图标网站ICO图标若想全部添加到网页中,有什么简便方法吗?什么是cookie有时遇到网页提示禁止第三方cookie是什么意思?招行信用卡还款招商信用卡怎么还款呢t320T320是3G手机吗,有TX用过吗?怎么样啊?互动电视怎么用互动电视上网网络购物的发展网络购物的发展对策暂停线程Java里如何暂停一个线程,达到一定条件后又唤醒线程?科学计算器说明书计算器的使用方法?约束是什么意思约束,是什么意思。如有回答,请详细,
免费域名注册网站 blackfriday Hello图床 12306抢票助手 中国电信测速112 共享主机 什么是服务器托管 能外链的相册 爱奇艺会员免费试用 Updog 双线机房 万网服务器 汤博乐 七十九刀 美国asp空间 hosts文件修改 此网页包含的内容将不使用安全的https 跟踪路由 ddos攻击小组 koss耳机 更多