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

背包问题回溯法  时间: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

Dynadot多种后缀优惠域名优惠码 ,.COM域名注册$6.99

Dynadot 是一家非常靠谱的域名注册商家,老唐也从来不会掩饰对其的喜爱,目前我个人大部分域名都在 Dynadot,还有一小部分在 NameCheap 和腾讯云。本文分享一下 Dynadot 最新域名优惠码,包括 .COM,.NET 等主流后缀的优惠码,以及一些新顶级后缀的优惠。对于域名优惠,NameCheap 的新后缀促销比较多,而 Dynadot 则是对于主流后缀的促销比较多,所以可以各取所...

快云科技,美国VPS 2H5G独享20M 仅售19.8/月  年付仅需148

快云科技已稳步运行进两年了 期间没出现过线路不稳 客户不满意等一系列问题 本司资质齐全 持有IDC ICP ISP等正规手续 有独特的网站设计理念 在前几天刚是参加过魔方系统举行的设计大赛拿获最佳设计奖第一名 本公司主营产品 香港弹性云服务器,美国vps和日本vps,香港物理机,国内高防物理机以及美国日本高防物理机 2020年的国庆推出过一款香港的回馈用户特惠机 已作为传家宝 稳定运行 马上又到了...

LOCVPS-2021年6月香港便宜vps宽带升级,充值就送代金券,其它八折优惠!

LOCVPS怎么样?LOCVPS是一家成立于2011年的稳定老牌国人商家,目前提供中国香港、韩国、美国、日本、新加坡、德国、荷兰等区域VPS服务器,所有机房Ping延迟低,国内速度优秀,非常适合建站和远程办公,所有机房Ping延迟低,国内速度优秀,非常适合做站。XEN架构产品的特点是小带宽无限流量、不超售!KVM架构是目前比较流行的虚拟化技术,大带宽,生态发展比较全面!所有大家可以根据自己业务需求...

背包问题回溯法为你推荐
rangepython 的range()函数怎么使用,为什么单独运行print(range(1,5))输出还是range(1,5),而不是[1,2,3,4]优翼奇瑞优翼车子拉缸气缸是维修还是换。换的话大概多少钱?按键精灵教程学按键精灵需要学些什么基础知识burndown如何画burndown chart工作经验介绍个人工作经历简介要怎么写工作经验介绍个人简历中的服务员工作经验怎么写比较好淘宝推广网站谁有好的淘宝推广网站介绍下哦!或推广技巧!海淀区公司注册在北京如何注册公司海淀区公司注册北京海淀培训公司注册如何办理?韩文在线翻译韩语在线翻译
asp主机 免费网站域名注册 美国vps评测 sugarhosts mediafire godaddy 灵动鬼影 微信收钱 有奖调查 gtt 东莞服务器 购买国外空间 独享主机 smtp服务器地址 东莞主机托管 cdn网站加速 重庆服务器 上海联通 香港博客 windowsserver2008r2 更多