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

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

轻云互联22元/月,美国硅谷、圣何塞CN2GIA云服务器,香港沙田cn2建站vps仅25元/月

轻云互联怎么样?轻云互联,广州轻云网络科技有限公司旗下品牌,2018年5月成立以来,轻云互联以性价比的价格一直为提供个人,中大小型企业/团队云上解决方案。本次轻云互联送上的是美国圣何塞cn2 vps(免费50G集群防御)及香港沙田cn2 vps(免费10G集群防御)促销活动,促销产品均为cn2直连中国大陆线路、采用kvm虚拟技术架构及静态内存。目前,轻云互联推出美国硅谷、圣何塞CN2GIA云服务器...

享有云:美国BGP云服务器低至20元/月起,首月打折;香港2核2G2M仅50元/月起

享有云怎么样?享有云是一家新的国内云服务器商家,目前提供国内、香港及海外地区的云服务器,拥有多线路如:BGP线路、CN2线路、高防等云服务器,并且提供稳定、安全、弹性、高性能的云端计算服务,实时满足您的多样性业务需求。目前,美国bgp云服务器,5M带宽,低至20元/月起,270元/年起,首月打折;香港2核2G2M仅50元/月起,450元/年起!点击进入:享有云官方网站地址享有云优惠活动:一、美国B...

Budgetvm12核心 16G 500 GB SSD 或者 2 TB SATA 10GB  20 TB  99美金

Budgetvm(原EZ机房),2005年成立的美国老品牌机房,主打美国4个机房(洛杉矶、芝加哥、达拉斯、迈阿密)和日本东京机房的独立服务器和VPS业务,而且不限制流量,默认提供免费的1800G DDoS防御服务,支持IPv6和IPMI,多种免费中文操作系统可供选择,独立服务器主打大硬盘,多硬盘,大内存,用户可以在后台自行安装系统等管理操作!内存可定制升级到1536G,多块硬盘随时加,14TBSA...

背包问题回溯法为你推荐
fast路由器路由器fast怎么设置无线网络win10发布Win10什么时候发布a8处理器AMD A8处理器与I5比怎么样光纤是什么光纤是什么google地图api如何使用GOOGLE EARTH 的API开发自己的应用程序antiarp电脑一开机就出现发现新硬件xAntiArp Miniport,提示安装,很是影响开机速度,怎么办?t320平板电脑三星 galaxy tab pro t320怎么样硬盘分区格式化硬盘分区后怎么格式化code查询手机CODE查询乐辞乐组词有哪些
网站域名备案 仿牌空间 香港vps99idc 流媒体服务器 softbank官网 日志分析软件 华为云主机 地址大全 卡巴斯基永久免费版 智能骨干网 免费个人空间申请 可外链网盘 个人免费主页 跟踪路由命令 空间首页登陆 google台湾 宏讯 什么是web服务器 东莞服务器托管 php服务器 更多