贪心算法实现01背包问题

合集下载

贪心算法-01背包问题

贪心算法-01背包问题

贪⼼算法-01背包问题1、问题描述:给定n种物品和⼀背包。

物品i的重量是wi,其价值为vi,背包的容量为C。

问:应如何选择装⼊背包的物品,使得装⼊背包中物品的总价值最⼤?形式化描述:给定c >0, wi >0, vi >0 , 1≤i≤n.要求找⼀n元向量(x1,x2,…,xn,), xi∈{0,1}, ∋ ∑ wi xi≤c,且∑ vi xi达最⼤.即⼀个特殊的整数规划问题。

2、最优性原理:设(y1,y2,…,yn)是 (3.4.1)的⼀个最优解.则(y2,…,yn)是下⾯相应⼦问题的⼀个最优解:证明:使⽤反证法。

若不然,设(z2,z3,…,zn)是上述⼦问题的⼀个最优解,⽽(y2,y3,…,yn)不是它的最优解。

显然有∑vizi > ∑viyi (i=2,…,n)且 w1y1+ ∑wizi<= c因此 v1y1+ ∑vizi (i=2,…,n) > ∑ viyi, (i=1,…,n)说明(y1,z2, z3,…,zn)是(3.4.1)0-1背包问题的⼀个更优解,导出(y1,y2,…,yn)不是背包问题的最优解,⽭盾。

3、递推关系:设所给0-1背包问题的⼦问题的最优值为m(i,j),即m(i,j)是背包容量为j,可选择物品为i,i+1,…,n时0-1背包问题的最优值。

由0-1背包问题的最优⼦结构性质,可以建⽴计算m(i,j)的递归式:注:(3.4.3)式此时背包容量为j,可选择物品为i。

此时在对xi作出决策之后,问题处于两种状态之⼀:(1)背包剩余容量是j,没产⽣任何效益;(2)剩余容量j-wi,效益值增长了vi ;使⽤递归C++代码如下:#include<iostream>using namespace std;const int N=3;const int W=50;int weights[N+1]={0,10,20,30};int values[N+1]={0,60,100,120};int V[N+1][W+1]={0};int knapsack(int i,int j){int value;if(V[i][j]<0){if(j<weights[i]){value=knapsack(i-1,j);}else{value=max(knapsack(i-1,j),values[i]+knapsack(i-1,j-weights[i]));}V[i][j]=value;}return V[i][j];}int main(){int i,j;for(i=1;i<=N;i++)for(j=1;j<=W;j++)V[i][j]=-1;cout<<knapsack(3,50)<<endl;cout<<endl;}不使⽤递归的C++代码:简单⼀点的修改//3d10-1 动态规划背包问题#include <iostream>using namespace std;const int N = 4;void Knapsack(int v[],int w[],int c,int n,int m[][10]);void Traceback(int m[][10],int w[],int c,int n,int x[]);int main(){int c=8;int v[]={0,2,1,4,3},w[]={0,1,4,2,3};//下标从1开始int x[N+1];int m[10][10];cout<<"待装物品重量分别为:"<<endl;for(int i=1; i<=N; i++){cout<<w[i]<<" ";}cout<<endl;cout<<"待装物品价值分别为:"<<endl;for(int i=1; i<=N; i++){cout<<v[i]<<" ";}cout<<endl;Knapsack(v,w,c,N,m);cout<<"背包能装的最⼤价值为:"<<m[1][c]<<endl;Traceback(m,w,c,N,x);cout<<"背包装下的物品编号为:"<<endl;for(int i=1; i<=N; i++){if(x[i]==1){cout<<i<<" ";}}cout<<endl;return 0;}void Knapsack(int v[],int w[],int c,int n,int m[][10]){int jMax = min(w[n]-1,c);//背包剩余容量上限范围[0~w[n]-1] for(int j=0; j<=jMax;j++){m[n][j]=0;}for(int j=w[n]; j<=c; j++)//限制范围[w[n]~c]{m[n][j] = v[n];}for(int i=n-1; i>1; i--){jMax = min(w[i]-1,c);for(int j=0; j<=jMax; j++)//背包不同剩余容量j<=jMax<c{m[i][j] = m[i+1][j];//没产⽣任何效益}for(int j=w[i]; j<=c; j++) //背包不同剩余容量j-wi >c{m[i][j] = max(m[i+1][j],m[i+1][j-w[i]]+v[i]);//效益值增长vi }}m[1][c] = m[2][c];if(c>=w[1]){m[1][c] = max(m[1][c],m[2][c-w[1]]+v[1]);}}//x[]数组存储对应物品0-1向量,0不装⼊背包,1表⽰装⼊背包void Traceback(int m[][10],int w[],int c,int n,int x[]){for(int i=1; i<n; i++){if(m[i][c] == m[i+1][c]){x[i]=0;}else{x[i]=1;c-=w[i];}}x[n]=(m[n][c])?1:0;}运⾏结果:算法执⾏过程对m[][]填表及Traceback回溯过程如图所⽰:从m(i,j)的递归式容易看出,算法Knapsack需要O(nc)计算时间; Traceback需O(n)计算时间;算法总体需要O(nc)计算时间。

0_1背包问题的贪心局部搜索算法研究

0_1背包问题的贪心局部搜索算法研究
从 RCL 中随机选择一件物品 y; 如果 y的重量不违反背包容量 ,把 y放入背包 ,标记 y,并且更新背包容量 ; 否则中止循环 ; } fo r ( i = 1; i ≤ n; i++ ) 检查背包外是否还有物品可放入背包 ; 产生一个可行解 x,计算放入背包的物品总价值 ; }
案. 拓宽邻域的办法是产生邻居 ,其途径主要有交换. 比较所得方案的总价值 ,若总价值增加则表示已找到一 个改进解 ,将得到的最好解作为局部最优解返回 ,搜索阶段结束. 若构造阶段得到的初始可行解已是当前局 部最优解 ,则局部搜索阶段返回的即是初始可行解.
可以选择不同的贪心策略应用于算法. 0 - 1背包问题最常用的贪心策略有价值贪心准则 ( vi ) 、重量贪 心准则 (w i ) 以及价值密度 ( vi /w i ) 贪心准则等. 本文所提出的两种算法均采用价值密度 ( vi /w i )贪心准则 ,并 且根据每次迭代 RCL 是否更新分别称为固定候选算法和变化候选算法. 2. 2 固定候选算法
中图分类号 : TP391
文献标识码 : A 文章编号 : 1009 - 7821 (2009) 05 - 0066 - 05
The study on greedy loca l search a lgor ithm of 0 - 1 knapsack problem
L IN Hong
背包问题 ( knap sack p roblem ,简称 KP)是一类在给定约束条件的情况下 ,求最大值的组合优化问题 ,是典 型的非确定多项式 ( non2determ inistic polynom ial, NP)完全难题. 解决该问题无论在理论上 ,还是在实际中都 具有重要的意义. 许多实际工程的优化问题都可以归结为背包问题 ,典型问题有 :处理机和数据库在分布式 计算机系统上的分配问题 、资源分配问题 、厂址选择问题 、货物装载问题 、批量切割问题 、项目选择决策问题 、 削减库存问题等. 随着网络技术的不断发展 ,背包公钥密码在电子商务中的公钥设计中也起着重要的作 用 [1 ]. 同时 ,在设计解决大量的复杂组合优化问题算法时 ,背包问题往往作为子问题出现. 背包问题的算法改 进 ,对复杂组合优化问题算法的改良是十分有益的. 因此 ,在近几十年中 , KP建模与算法的研究受到广泛的 重视 ,研究前景十分广阔.

背包问题解析(一)-贪心算法

背包问题解析(一)-贪心算法

背包问题解析(⼀)-贪⼼算法⼀、题⽬:有N件物品和⼀个容量为V的背包。

第i件物品的重量是w[i],价值是v[i]。

求解将哪些物品装⼊背包可使这些物品的重量总和不超过背包容量,且价值总和最⼤。

⼆、解决思路:本题刚开始的解题的时候,想采取贪⼼算法来解决,也就是将放⼊的物品的性价⽐按照从⾼到低进⾏排序,然后优先放优先级⾼的,其次优先级低的。

三、代码实现(python)1# 重量w=[5,4,3,2]2# 价值v=[6,5,4,3]3 b=[]4 m=int(input("请输⼊背包的最⼤重量:"))5 n=int(input("请输⼊商品的数量:"))6for i in range(n):7 a=input("请分别输⼊重量和价值,以空格隔开:")8 a=a.split("")9for i in range(len(a)):10 a[i]=int(a[i])11 b.append(a)12print("加载初始化:",b)13for i in range(len(b)):14for j in range(i+1,len(b)):15if b[i][1]/b[i][0]<b[j][1]/b[j][0]:16 b[i],b[j]=b[j],b[i]17print("性价⽐排序:",b)18 v=019 c=[]20for i in range(len(b)):21if m-b[i][0]>0:22 m=m-b[i][0]23 c.append(b[i])24 v+=b[i][1]25print("放⼊背包:",c)26print("最⼤价值为:",v)打印结果:四、算法分析:贪⼼选择是指所求问题的整体最优解可以通过⼀系列局部最优的选择,即贪⼼选择来达到。

01背包贪心算法

01背包贪心算法

0—1背包问题一、实验目的学习掌贪心算法法思想。

二、实验内容用分支限定法求解0—1背包问题,并输出问题的最优解。

0—1背包问题描述如下:给定n种物品和一背包。

物品i的重量是Wi,其价值为Vi,背包的容量是c,问应如何选择装入背包中的物品,使得装入背包中物品的总价值最大。

三、实验条件Jdk1.5以上四、需求分析对于给定n种物品和一背包。

在容量最大值固定的情况下,要求装入的物品价值最大化。

五、基本思想:总是对当前的问题作最好的选择,也就是局部寻优。

最后得到整体最优。

总是选择单位价值最高的物品六、详细设计package sunfa;/**** @author Administrator*/import java.util.*;public class Greedy_Algorithm {static Element dd[];static int CurrentV ;static int CurrentC;static StringBuffer stb= new StringBuffer();public static int knapasck(int c, int[] w, int[] v, int[] x) {int n = v.length;Element d [] = new Element[n];for(int i = 0 ;i< n; i++){d[i]=new Element(w[i],v[i],i+1);}//按单位重量价值升序排序Arrays.sort(d);dd =d;/*for(int i = 0; i<d.length ;i++){System.out.println("重量" +d[i].ww+ "单位价值"+d[i].wv);}*/int i = 0;int MaxV2 = 0;for(i=0;i<n;i++)x[i] = 0;for(i=0;i<n;i++){if(d[i].ww>c)break;else{x[i] = d[i].tag; //x【】中存的是原元素的序号MaxV2 = MaxV2+d[i].value;c = c -d[i].ww;CurrentC =c ;stb.append("选择第" + d[i].tag + "个当前价值:"+MaxV2+ "剩余容量:"+c+"\n");}}return MaxV2;}}class Element implements Comparable{int ww; //物品重量int value; //物品价值double wv;//物品单位重量的价值int tag;//物品的标志是第一个物品public Element(int w ,int vv ,int tag){this.tag = tag;this.ww = w;this.value = vv;wv = (double)vv/w;}//对象比较的方法public int compareTo(Object x){Element temp = (Element)x;double rate = (double)ww/value;double temprate = (double)temp.ww/temp.value;if(rate<temprate)return -1;if(rate==temprate)return 0;elsereturn 1;}}运行结果(用列一)用列二上述结果显示:贪心算法不是总是最优的.动态规划与贪心算法比较;动态规划法又和贪婪算法有些一样,在动态规划中,可将一个问题的解决方案视为一系列决策的结果。

01背包各种算法代码实现总结(穷举,贪心,动态,递归,回溯,分支限界)

01背包各种算法代码实现总结(穷举,贪心,动态,递归,回溯,分支限界)

01背包各种算法代码实现总结(穷举,贪⼼,动态,递归,回溯,分⽀限界)2020-05-22所有背包问题实现的例⼦都是下⾯这张图01背包实现之——穷举法:1.我的难点:(1)在⽤穷举法实现代码的时候,我⾃⼰做的时候认为最难的就是怎么将那么多种情况表⽰出来,⼀开开始想⽤for循环进⾏多次嵌套,但是太⿇烦,⽽且还需要不断的进⾏各种标记。

我现在的⽔平实在太菜,然后就在⼀篇中看到⼀个特别巧妙的枚举算法,如下所⽰:int fun(int x[n]){int i;for(i=0;i<n;i++)if(x[i]!=1) {x[i]=1; return;}//从遇到的第⼀位开始,若是0,将其变成1,然后结束for循环,得到⼀种解法else x[i]=0;return;//从第⼀位开始,若是1,将其变成0,然后继续循环,若再循环的时候遇到0,则将其变为1,结束循环。

得到另⼀种解法。

} 虽然我现在也不知道为什么会这样,但是确实是个很好的规律,找到这个规律后,就可以很轻松的⾃⼰写出各种排列情况,以后遇到排列的问题,就⽤这个⽅法。

语⾔不好描述,上图⽚演⽰(是歪的,凑活看吧。

):(2)算法思想:x[i]的值为0/1,即选或者不选w[i]的值表⽰商品i的重量v[i]的值表⽰商品的价值所以这个算法最核⼼的公式就是tw=x[1]*w[1]+x[2]*w[2]+.......+x[n]*w[n]tv=x[1]*w[1]+x[2]*v[2]+......+x[n]*v[n]tv1:⽤于存储当前最优解limit:背包容量如果 tw<limit&&tv>tv1 则可以找到最优解2.代码实现(借鉴)#include<stdio.h>#include<iostream>using namespace std;#define n 4void possible_solution(int x[n]){int i;for(i=0;i<4;i++) //n=4,有2^4-1种解法if(x[i]!=1){x[i]=1;return; //从遇到的第⼀位开始,若是0,将其变成1,然后结束循环,得到⼀种解法}elsex[i]=0;return;//从第⼀位开始,若是1,将其变成0,然后继续循环,若再循环的时候遇到0,则将其变为1,结束循环。

贪心法求解01背包问题

贪心法求解01背包问题

贪心法的关键是度量标准,这个程序的度量标准有三个占用空间最小物品效益最大物品效益/占用空间最大程序实现如下:至于文件的操作不加论述。

#include <stdio.h>#include <stdlib.h>typedef struct{char name[10];int weight;int price;}Project;Project *Input(Project *wp,int TotalNum,int TotalWeight) {int i,j,Way,GoBack,RealWeight,RealPrice,TotalPrice;Project temp;do{printf("请选择:\n");printf(" 1.空间最优\n");printf(" 2.价格最优\n");printf(" 3.价格空间比最优\n");scanf("%d",&Way);switch(Way){case 1:for(i=0;i<TotalNum;i++)for(j=0;j<TotalNum-i-1;j++){if(wp[j].weight>wp[j+1].weight){temp=wp[j];wp[j]=wp[j+1];wp[j+1]=temp;}}break;case 2:for(i=0;i<TotalNum;i++)for(j=0;j<TotalNum-i-1;j++){if(wp[j].price<wp[j+1].price){temp=wp[j];wp[j]=wp[j+1];wp[j+1]=temp;}}break;case 3:for(i=0;i<TotalNum;i++)for(j=0;j<TotalNum-i-1;j++){if((float)wp[j].price/(float)wp[j].weight<(float)wp[j+1].price/(float)wp[j+1].weight){temp=wp[j];wp[j]=wp[j+1];wp[j+1]=temp;}}break;default:{printf("输入错误!\n");exit(1);}}i=0;RealWeight=wp[0].weight;TotalPrice=wp[0].price;printf("被装入背包的物品是:\n(物品名价格重量)\n");while(RealWeight<TotalWeight&&i<TotalNum){printf("%s %d %d\n",wp[i].name,wp[i].price,wp[i].weight);i++;RealWeight+=wp[i].weight;TotalPrice+=wp[i].price;}RealWeight-=wp[i].weight;TotalPrice-=wp[i].price;printf("求解结束!背包所装物品总重量:%d,总价值:%d\n",RealWeight,TotalPrice);printf("退出本次测试请按0!\n");scanf("%d",&GoBack);}while(GoBack!=0);return wp;}void main(){int InputWay,TotalNum,i,TotalWeight,RealWeight,Goon,TotalPrice;Project *Array;FILE *fp;do{printf("请选择数据录入方式!\n");printf(" 1.文件读入\n");printf(" 2.键盘输入\n");scanf("%d",&InputWay);switch(InputWay){case 1:printf("请输入背包最大容量:");scanf("%d",&TotalWeight);fp=fopen("data.txt","r");fscanf(fp,"%d\n",&TotalNum);if((Array=(Project*)malloc(TotalNum*sizeof(Project)))==NULL){printf("内存已满,申请空间失败!\n");exit(1);}else{for(i=0;i<TotalNum;i++){fscanf(fp,"%s %d %d\n",&Array[i].name,&Array[i].price,&Array[i].weight);}}fclose(fp);Array=Input(Array,TotalNum,TotalWeight);break;case 2:printf("请输入物品数量及背包容量\n");scanf("%d%d",&TotalNum,&TotalWeight);if((Array=(Project*)malloc(TotalNum*sizeof(Project)))==NULL){printf("内存已满,申请空间失败!\n");exit(1);}else{printf("请输入:物品名价格重量\n");for(i=0;i<TotalNum;i++)scanf("%s%d%d",&Array[i].name,&Array[i].price,&Array[i].weight);}Array=Input(Array,TotalNum,TotalWeight);break;default:{printf("输入错误!\n");exit(1);}}printf("继续其他数据测试请按1\n");scanf("%d",&Goon);}while(Goon==1);delete Array;}。

基于贪心遗传算法求解0-1背包问题

基于贪心遗传算法求解0-1背包问题

S o l u t i o n t o 0 - I Kna p s a c k Pr o bl e m Ba s e d o n t he Gr e e dy - g e ne t i c Al g o r i t h m
Y A 0 We n j u a n ,WU F e i ,X I A Q i a n ,S HA O B i a o ,Z H A N G L o n g z h o n g ,L I U J i a n
( 兰 州 交 通 大 学 交 通 运 输 学 院 ,甘 肃 兰州 7 3 0 0 7 0 )


在 解决 0—1背 包问题 中,将贪心算法和 遗传算 法相 结合 ,提 出 了贪心遗 传算 法。通过 算法构 造 出更优
的新 算子 ,与 原有 算子相 比 ,既加 快 了算法的收敛速度 ,又克服 了传统方法容 易陷入局 部最优 的特点 ,提 高 了搜 索效
a l s o a v o i d s t h e l o c a l o p t i mu m t r a p o f t h e t r a d i t i o n l a me t h o d, t h u s i mp r o v i n g s e a r c h e ic f i e n c y . Th e c o mp u t e r s i mu l a -
实际 工作 中 , 越 来越 多 的领域运 用 到 了背 包 问题 。
m a x f ( x 2 , …)=∑P
目标 函数
求解 背包 问题 的方 法 可分 为 启 发 式算 法 , 如 贪 心 算法 、 模 拟退 火算 法 、 蚁群算 法 ; 最优 化算 法 , 如 动态 规 划算 法 、 回溯法 、 分支 定界 法等 J 。这 些算 法均 能找 到 相应 的最优 解 , 但 也 均有各 自的局 限性及 缺 陷 。 本文 介 绍 了贪 心 算法 和遗 传算 法 求 解 0—1背 包 问题 , 并在其基础上提出基 于贪心算法的遗传算法来 解决 背包 问题 。 最后 , 运用 计算 机 仿 真 技 术来 验 证 混 合 遗 传 算 法 的设计 。这 样 , 即克 服 了传 统算 法 的缺 陷 , 又 加快 了算

用贪心法求解0-1背包问题

用贪心法求解0-1背包问题

算法设计与分析期末论文题目用贪心法求解“0-1背包问题”专业计算机科学与技术班级09计算机一班学号0936021姓名黄帅日期2011年12月28日一、0-1背包问题的算法设计策略分析1.引言对于计算机科学来说,算法的概念是至关重要的,例如,在一个大型软件系统的开发中,设计出有效的算法将起决定性的作用。

算法是解决问题的一种方法或一个过程。

程序是算法用某种设计语言具体实现描。

计算机的普及极大的改变了人们的生活。

目前,各行业、各领域都广泛采用了计算机信息技术,并由此产生出开发各种应用软件的需求。

为了以最小的成本、最快的速度、最好的质量开发出适合各种应用需求的软件,必须遵循软件工程的原则。

设计一个高效的程序不仅需要编程小技巧,更需要合理的数据组织和清晰高效的素算法,这正是计算机科学领域数据结构与算法设计所研究的主要内容。

2. 算法复杂性分析的方法介绍算法复杂性是算法运行所需要的计算机资源的量,需要时间资源的量称为时间复杂性,需要的空间资源的量称为空间复杂性。

这个量应该只依赖于算法要解的问题的规模、算法的输入和算法本身的函数。

如果分别用N 、I 和A 表示算法要解问题的规模、算法的输入和算法本身,而且用C 表示复杂性,那么,应该有C=F(N,I,A)。

一般把时间复杂性和空间复杂性分开,并分别用T 和S 来表示,则有: T=T(N,I)和S=S(N,I) 。

(通常,让A 隐含在复杂性函数名当中最坏情况下的时间复杂性:最好情况下的时间复杂性:平均情况下的时间复杂性:其中DN 是规模为N 的合法输入的集合;I*是DN 中使T(N, I*)达到Tmax(N)的合法输入; 是中使T(N, )达到Tmin(N)的合法输入;而P(I)是在算法的应用中出现输入I 的概率。

算法复杂性在渐近意义下的阶:渐近意义下的记号:O 、Ω、θ、o 设f(N)和g(N)是定义在正数集上的正函数。

O 的定义:如果存在正的常数C 和自然数N0,使得当N ≥N0时有f(N)≤Cg(N),则称函数f(N)当N 充分大时上有界,且g(N)是它的一个上界,记为f(N)=O(g(N))。

0-1背包问题c语言实现

0-1背包问题c语言实现

0-1背包问题c语言实现问题描述:给定n种物品和一个背包。

物品i的重量为w[i],其价值为v[i],背包的容量为c。

应如何选择装入背包的物品,使得装入背包中的物品的总价值最大。

每种物品最多装入一次。

0-1背包问题:对于要装入背包中的物品,只有两种选择:全部装入或者不装入。

背包问题:对于要装入背包中的物品,可以选择装入一部分,不一定要全部装入背包中。

算法分析:使用贪心策略求解此类问题时,首先要选出最优的度量标准。

可供选择的度量标准有三种:价值,容量,单位价值(v/w,价值/重量)。

显然,价值高的物品容量可能太大,容量大的物品价值也可能很低。

最优的度量标准是单位价值。

背包问题算法思路:1、将各个物品按照单位价值由高到低排序;2、取价值最高者放入背包;3、计算背包的剩余空间;4、重复2-3步,直到背包剩余容量=0或者物品全部装入背包为止(对于0-1背包,终止条件为背包剩余容量无法装入任意一件物品或者物品全部装入背包)。

下面是C语言实现(DEV c++4.9.9.2运行通过)[cpp]#includevoid package(int n,float c,float v[],float w[],float x[]); void package0_1(int n,float c,float v[],float w[],float x[]);int main(void){int n = 3;float c = 20;float v[] = {24,15,25};float w[] = {15,10,18};//已经按照单位价值降序排列float *x;x = (float*)malloc(sizeof(float)*n);printf("******背包*******\n");package(n,c,v,w,x);printf("*******0-1背包******\n");package0_1(n,c,v,w,x);system("PAUSE");}/** 背包问题* n:物品个数* c:背包容量* v[]:每个物品的价值* w[]:每个物品的重量(这里已经按照单位价值降序排列)* x[]:物品是否放入背包(0表示不放,1表示全部放入,0-1放入一部分)*/void package(int n,float c,float v[],float w[],float x[]){int i;for(i=0;i{x[i] = 0;//初始状态,所有物品都没有被放入背包}for(i=0;i{if(w[i] > c){break;}x[i] = 1;c = c - w[i];printf("放入第%d件物品,背包剩余容量%f.\n",(i+1),c);}if(i<=n)//还可以放入一个物品的一部分{x[i] = c/w[i];printf("放入第%d件物品的%f部分.背包剩余容量为0.\n",(i+1),w[i]*x[i]);}}/** 0-1背包问题* n:物品个数* c:背包容量* v[]:每个物品的价值* w[]:每个物品的重量(这里已经按照单位价值降序排列)* x[]:物品是否放入背包(0表示不放,1表示全部放入)*/void package0_1(int n,float c,float v[],float w[],float x[]) {int i;for(i=0;i{x[i] = 0;//初始状态,所有物品都没有被放入背包}for(i=0;i{if(w[i] > c){break;}x[i] = 1;c = c - w[i];printf("放入第%d件物品,背包剩余容量%f.\n",(i+1),c); }}#includevoid package(int n,float c,float v[],float w[],float x[]); void package0_1(int n,float c,float v[],float w[],float x[]);int main(void){int n = 3;float c = 20;float v[] = {24,15,25};float w[] = {15,10,18};//已经按照单位价值降序排列float *x;x = (float*)malloc(sizeof(float)*n);printf("******背包*******\n");package(n,c,v,w,x);printf("*******0-1背包******\n");package0_1(n,c,v,w,x);system("PAUSE");}/** 背包问题* n:物品个数* c:背包容量* v[]:每个物品的价值* w[]:每个物品的重量(这里已经按照单位价值降序排列)* x[]:物品是否放入背包(0表示不放,1表示全部放入,0-1放入一部分)*/void package(int n,float c,float v[],float w[],float x[]){int i;for(i=0;i<n;i++){x[i] = 0;//初始状态,所有物品都没有被放入背包}for(i=0;i<n;i++){if(w[i] > c){break;}x[i] = 1;c = c - w[i];printf("放入第%d件物品,背包剩余容量%f.\n",(i+1),c);}if(i<=n)//还可以放入一个物品的一部分{x[i] = c/w[i];printf("放入第%d件物品的%f部分.背包剩余容量为0.\n",(i+1),w[i]*x[i]);}}/** 0-1背包问题* n:物品个数* c:背包容量* v[]:每个物品的价值* w[]:每个物品的重量(这里已经按照单位价值降序排列)* x[]:物品是否放入背包(0表示不放,1表示全部放入)*/void package0_1(int n,float c,float v[],float w[],float x[]){int i;for(i=0;i<n;i++){x[i] = 0;//初始状态,所有物品都没有被放入背包}for(i=0;i<n;i++){if(w[i] > c){break;}x[i] = 1;c = c - w[i];printf("放入第%d件物品,背包剩余容量%f.\n",(i+1),c);}}虽然背包问题和0-1背包都具有最优子结构性质,但是背包问题用贪心算法求出来的是最优解,0-1背包问题通过贪心算法得不到最优解,因为无法保证最后能将背包装满,部分闲置的背包空间使总价值降低了。

01背包问题(回溯算法实现)

01背包问题(回溯算法实现)

01背包问题(回溯算法实现)问题描述:有n件物品和⼀个容量为c的背包。

第i件物品的价值是v[i],重量是w[i]。

求解将哪些物品装⼊背包可使价值总和最⼤。

所谓01背包,表⽰每⼀个物品只有⼀个,要么装⼊,要么不装⼊。

今天下午的算法复习课,⽼师提的各种算法经典问题时,出现频率就是01背包问题了!动态规划、回溯法、分⽀限界法,在贪⼼算法时也提到注意背包问题,当然 01背包问题不能⽤贪⼼算法实现,不能保证能得到最优解。

回溯法是最近学的,所以试着⽤C语⾔将其实现了下,下⾯作以分析,后期将会继续⽤其他两种算法实现01背包问题,并做⽐较。

回溯法:01背包属于找最优解问题,⽤回溯法需要构造解的⼦集树。

在搜索状态空间树时,只要左⼦节点是可⼀个可⾏结点,搜索就进⼊其左⼦树。

对于右⼦树时,先计算上界函数,以判断是否将其减去,剪枝啦啦!上界函数bound():当前价值cw+剩余容量可容纳的最⼤价值<=当前最优价值bestp。

为了更好地计算和运⽤上界函数剪枝,选择先将物品按照其单位重量价值从⼤到⼩排序,此后就按照顺序考虑各个物品。

下⾯直接贴代码吧:#include <stdio.h>#include <conio.h>int n;//物品数量double c;//背包容量double v[100];//各个物品的价值double w[100];//各个物品的重量double cw = 0.0;//当前背包重量double cp = 0.0;//当前背包中物品价值double bestp = 0.0;//当前最优价值double perp[100];//单位物品价值排序后int order[100];//物品编号int put[100];//设置是否装⼊//按单位价值排序void knapsack(){inti,j;inttemporder = 0;double temp= 0.0;for(i=1;i<=n;i++)perp[i]=v[i]/w[i];for(i=1;i<=n-1;i++){for(j=i+1;j<=n;j++)if(perp[i]<perp[j])//冒泡排序perp[],order[],sortv[],sortw[]{temp = perp[i];perp[i]=perp[i];perp[j]=temp;temporder=order[i];order[i]=order[j];order[j]=temporder;temp = v[i];v[i]=v[j];v[j]=temp;temp=w[i];w[i]=w[j];w[j]=temp;}}}//回溯函数void backtrack(int i){doublebound(int i);if(i>n){bestp = cp;return;}if(cw+w[i]<=c){cw+=w[i];cp+=v[i];put[i]=1;backtrack(i+1);cw-=w[i];cp-=v[i];}if(bound(i+1)>bestp)//符合条件搜索右⼦数backtrack(i+1);}//计算上界函数double bound(int i){doubleleftw= c-cw;double b =cp;while(i<=n&&w[i]<=leftw){leftw-=w[i];b+=v[i];i++;}if(i<=n)b+=v[i]/w[i]*leftw;returnb;}int main(){int i;printf("请输⼊物品的数量和容量:");scanf("%d%lf",&n,&c);printf("请输⼊物品的重量和价值:");for(i=1;i<=n;i++){printf("第%d个物品的重量:",i);scanf("%lf",&w[i]);printf("价值是:");scanf("%lf",&v[i]);order[i]=i;}knapsack();backtrack(1);printf("最有价值为:%lf\n",bestp);printf("需要装⼊的物品编号是:");for(i=1;i<=n;i++){if(put[i]==1)printf("%d ",order[i]);}return0;}运⾏结果截图:算法复杂度分析:上界函数bound()需要O(n)时间,在最坏的情况下有O(2^n)个右⼦结点需要计算上界,回溯算法backtrack需要的计算时间为O(n2^n)。

【算法问题】0-1背包问题

【算法问题】0-1背包问题

【算法问题】0-1背包问题 0-1背包问题:有⼀个贼在偷窃⼀家商店时,发现有n件物品,第i件物品价值v i元,重w i磅,此处v i与w i都是整数。

他希望带⾛的东西越值钱越好,但他的背包中⾄多只能装下W磅的东西,W为⼀整数。

应该带⾛哪⼏样东西?这个问题之所以称为0-1背包,是因为每件物品或被带⾛;或被留下;⼩偷不能只带⾛某个物品的⼀部分或带⾛同⼀物品两次。

在分数(部分)背包问题(fractional knapsack problem)中,场景与上⾯问题⼀样,但是窃贼可以带⾛物品的⼀部分,⽽不必做出0-1的⼆分选择。

可以把0-1背包问题的⼀件物品想象成⼀个⾦锭,⽽部分问题中的⼀件物品则更像⾦沙。

两种背包问题都具有最优⼦结构性质。

对0-1背包问题,考虑重量不超过W⽽价值最⾼的装包⽅案。

如果我们将商品j从此⽅案中删除,则剩余商品必须是重量不超过W-wj的价值最⾼的⽅案(⼩偷只能从不包括商品j的n-1个商品中选择拿⾛哪些)。

虽然两个问题相似,但我们⽤贪⼼策略可以求解背包问题,⽽不能求解0-1背包问题,为了求解部分数背包问题,我们⾸先计算每个商品的每磅价值v i/w i。

遵循贪⼼策略,⼩偷⾸先尽量多地拿⾛每磅价值最⾼的商品,如果该商品已全部拿⾛⽽背包未装满,他继续尽量多地拿⾛每磅价值第⼆⾼的商品,依次类推,直到达到重量上限W。

因此,通过将商品按每磅价值排序,贪⼼算法的时间运⾏时间是O(nlgn)。

为了说明贪⼼这⼀贪⼼策略对0-1背包问题⽆效,考虑下图所⽰的问题实例。

此例包含3个商品和⼀个能容纳50磅重量的背包。

商品1重10磅,价值60美元。

商品2重20磅,价值100美元。

商品3重30磅,价值120美元。

因此,商品1的每磅价值为6美元,⾼于商品2的每磅价值5美元和商品3的每磅价值4美元。

因此,上述贪⼼策略会⾸先拿⾛商品1。

但是,最优解应该是商品2和商品3,⽽留下商品1。

拿⾛商品1的两种⽅案都是次优的。

贪心算法实现01背包问题

贪心算法实现01背包问题

贪心算法实现01背包问题算法思想:贪心原则为单位价值最大且重量最小,不超过背包最大承重量为约束条件。

也就是说,存在单位重量价值相等的两个包,则选取重量较小的那个背包。

具体实现过程是:首先可以设置一个备份pvu类型的数组,在不破环原数据的情况下,对此备份数组按单位重量价值从大到小的排序。

依次设立两个指针i,j(其中i表示当前应该参与最佳pv值的元素指针,j表示符合约束条件的指针(单位重量价值PV最大,重量最小,不超过最大承重量约束)代码实现如下:#include <iostream>using namespace std;typedef struct{int v;int w;float pv;}pvu;void sortByPv(pvu [],int );int zeroneBags(pvu[],int,int,int * );void print(pvu a[],int n){for (int i=0;i<n;i++){cout<<a[i].w<<" "<<a[i].v<<" "<<a[i].pv<<endl;}cout<<endl;}int main(){int i,maxw;int w[]={1,2,3,2};int v[]={9,10,15,6};int n=sizeof(w)/sizeof(int );const int N=n;pvu arr[N];for (i=0;i<n;i++){arr[i].v=v[i];arr[i].w=w[i];arr[i].pv=v[i]*1.0/w[i];}int remained;cout<<"输入背包的最大承重量:\n";cin>>maxw;cout<<"最大价值为:"<<zeroneBags(arr,n,maxw,&remained)<<"\n还剩"<<remained<<"公斤空间未使用"<<endl;return 0;}void sortByPv(pvu arr[] ,int n){pvu t;int i,j;for (i=0;i<n-1;i++)for (j=0;j<n-1-i;j++)if (arr[j].pv<arr[j+1].pv){t=arr[j];arr[j]=arr[j+1];arr[j+1]=t;}}int zeroneBags(pvu arr[],int n,int maxw,int *e){int i=0,j,minw,totalv=0;int avail=maxw;sortByPv(arr,n); //按最大单位重量价值PV从大到小的排序while (avail&&i<n){minw=i;for (j=0;j<n;j++)if (arr[i].pv==arr[j].pv){if (arr[i].w>arr[j].w&&j>i){minw=j;}}if (arr[minw].w<=avail){avail-=arr[minw].w;totalv+=arr[minw].v;i++;}elsei++;}*e=avail;return totalv; }运行结果截图:。

python实现贪婪算法解决01背包问题

python实现贪婪算法解决01背包问题

python实现贪婪算法解决01背包问题⼀、背包问题01背包是在M件物品取出若⼲件放在空间为W的背包⾥,每件物品的体积为W1,W2⾄Wn,与之相对应的价值为P1,P2⾄Pn。

01背包是中最简单的问题。

01背包的约束条件是给定⼏种物品,每种物品有且只有⼀个,并且有权值和体积两个属性。

在01背包问题中,因为每种物品只有⼀个,对于每个物品只需要考虑选与不选两种情况。

如果不选择将其放⼊背包中,则不需要处理。

如果选择将其放⼊背包中,由于不清楚之前放⼊的物品占据了多⼤的空间,需要枚举将这个物品放⼊背包后可能占据背包空间的所有情况。

⼆、求解思路 当遇到这样的问题,我们可以换⼀种⾓度去思考,假设在⼀个100m3的房⼦⾥⾯,现在要将房⼦装满,同时要保证放⼊的物品个数最多以及装⼊的东西最重,现在⾝边有铁球和棉花,请问⼤家是放铁球进去好呢还是放棉花进去好呢?显⽽易见,放⼊铁球进去是最优选择。

但是原因是什么呢?很简单,就是因为铁球的密度较⼤,相同体积的铁球和棉花相⽐,铁球更重。

不过前提是放⼊第⼀个铁球时,铁球的体积V1⼩于等于100m3 ;放⼊第⼆个铁球时,铁球的体积V2 ⼩于等于(100-V1)m3;……;放⼊第n个铁球时,铁球的体积⼩于等于(100-∑n1Vn-1)m3 ,要是第n个铁球的体积⼤于(100- ∑n1Vn-1)m3 ,还真是不如放点单位体积更轻的棉花进去,说的极端点就是所有铁球的体积都⼤于100m3 ,还真不如随便放⼊点棉花进去合算。

所以总是放铁球进去,不考虑是否放⼊棉花,容易产⽣闲置空间,最终会得不到最优选择,可能只是最优选择的近似选择。

现在再次回到背包问题上,要使得背包中可以获得最⼤总价值的物品,参照铁球的例⼦我们可以知道选择单位重量下价值最⾼的物品放⼊为最优选择。

但是由于物品不可分割,⽆法保证能将背包刚好装满,最后闲置的容量⽆法将单位重量价值更⾼的物品放⼊,此时要是可以将单位重量价值相对低的物品放⼊,反⽽会让背包的总价值和单位重量的价值更⾼。

Python基于贪心算法解决背包问题示例

Python基于贪心算法解决背包问题示例

Python基于贪⼼算法解决背包问题⽰例本⽂实例讲述了Python基于贪⼼算法解决背包问题。

分享给⼤家供⼤家参考,具体如下:贪⼼算法(⼜称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择。

也就是说,不从整体最优上加以考虑,他所做出的是在某种意义上的局部最优解。

贪⼼算法不是对所有问题都能得到整体最优解,关键是贪⼼策略的选择,选择的贪⼼策略必须具备⽆后效性,即某个状态以前的过程不会影响以后的状态,只与当前状态有关。

完全背包问题:给定n个物品和⼀个容量为C的背包,物品i的重量是Wi,其价值为Vi,背包问题是如何选择⼊背包的物品,使得装⼊背包的物品的总价值最⼤,与0-1背包的区别是,在完全背包问题中,可以将物品的⼀部分装⼊背包,但不能重复装⼊。

设计算法的思路很简单,计算物品的单位价值,然后尽可能多的将单位重量价值⾼的物品放⼊背包中。

python实现代码如下:# coding=gbk# 完全背包问题,贪⼼算法import time__author__ = 'ice'class goods:def __init__(self, goods_id, weight=0, value=0):self.id = goods_idself.weight = weightself.value = value# 不适⽤于0-1背包def knapsack(capacity=0, goods_set=[]):# 按单位价值量排序goods_set.sort(key=lambda obj: obj.value / obj.weight, reverse=True)result = []for a_goods in goods_set:if capacity < a_goods.weight:breakresult.append(a_goods)capacity -= a_goods.weightif len(result) < len(goods_set) and capacity != 0:result.append(goods(a_goods.id, capacity, a_goods.value * capacity / a_goods.weight))return resultsome_goods = [goods(0, 2, 4), goods(1, 8, 6), goods(2, 5, 3), goods(3, 2, 8), goods(4, 1, 2)]start_time = time.clock()res = knapsack(6, some_goods)end_time = time.clock()print('花费时间:' + str(end_time - start_time))for obj in res:print('物品编号:' + str(obj.id) + ' ,放⼊重量:' + str(obj.weight) + ',放⼊的价值:' + str(obj.value), end=',')print('单位价值量为:' + str(obj.value / obj.weight))# 花费时间:2.2807240614677942e-05# 物品编号:3 ,放⼊重量:2,放⼊的价值:8,单位价值量为:4.0# 物品编号:0 ,放⼊重量:2,放⼊的价值:4,单位价值量为:2.0# 物品编号:4 ,放⼊重量:1,放⼊的价值:2,单位价值量为:2.0# 物品编号:1 ,放⼊重量:1,放⼊的价值:0.75,单位价值量为:0.75更多关于Python相关内容感兴趣的读者可查看本站专题:《》、《》、《》、《》、《》及《》希望本⽂所述对⼤家Python程序设计有所帮助。

贪心算法解决0-1背包问题

贪心算法解决0-1背包问题

贪心算法--0-1背包问题1、问题的描述有编号分别为a,b,c,d,e的五件物品,它们的重量分别是2,4,2,1,3,它们的价值分别是3,5,6,4,6,现在给你个承重为10的背包,如何让背包里装入的物品具有最大的价值总和?贪心算法的思想:贪心原则为单位价值最大且重量最小,不超过背包最大承重量为约束条件。

也就是说,存在单位重量价值相等的两个包,则选取重量较小的那个背包。

2、代码及注释#include <stdio.h>#define M 5//定义一个node结构体,用来存放物体的重量和价值struct node{float value;//价值float weight;//重量int flag; //用来判别这个物体是否装进背包}Node[M],temp;float Value,curvalue=0;//总价值和当前价值float Weight,curweight=0;//背包的最大承受重量和现有重量//按性价比排序void sort(){int i,j;//遍历所有物品for(i=0;i<M-1;i++){//与之后的物品进行比较for(j=i+1;j<M;j++){//判断性价比较最高性价比if((Node[i].value/(float)Node[i].weight)<Node[j].value/(float)Node[j].weight) {//进行交换temp=Node[i];Node[i]=Node[j];Node[j]=temp;}}}}//装载主要方法void load(){int i;//遍历所有物品for(i=0;i<M;i++){//判断加入物品否是否大于背包所能承载的最大重量 if((Node[i].weight+curweight)<=Weight){curvalue+=Node[i].value;curweight+=Node[i].weight;Node[i].flag=1;//进行标记}else{//进行标记Node[i].flag=0;}}}//进行结果的输出void putout(){int i;printf("选中物品的重量分别为:");for(i=0;i<M;i++){if(Node[i].flag){printf("%.2f ",Node[i].weight);}}printf("\n总价值为:%.2f",curvalue);}int main(){int i;printf("请输入物品的重量和价值:\n");for(i=0;i<M;i++){printf("请输入第%d个物品的重量和价值",i+1); scanf("%f%f",&Node[i].weight,&Node[i].value);}printf("\n请输入背包容积:");scanf("%f",&Weight);sort();load();putout();return 0;}3、运行结果(1)在某种情况下可以通过局部最优选择达到整体最优。

贪心法求解背包问题

贪心法求解背包问题
贪心法求解背包问题
问题描述

已知有n种物品和一个可容纳M重量的背包,每种物品i的重 量为。假定将物品i的一部分放入背包就会得到的效益,这里,, 。显 然,由于背包容量是M,因此,要求所有选中要装入背包的物品总重 量不得超过M.。如果这n件物品的总重量不超过M,则把所有物品装 入背包自然获得最大效益。现需解决的问题是,在这些物品重量的和 大于M的情况下,该如何装包,使得得到更大的效益值。由以上叙述, 可将这个问题形式表述如下: p i xi • 极 大 化目标函数 1i n • 约束条件 wi xi M • 1i n
0 xi 1, pi 0, wi 0,1 i n
算法分析

首先需确定最优的量度标准。这里考虑三种策略: • 策略1:按物品价值p降序装包, • 策略2:按物品重w升序装包 • 策略3:按物品价值与重量比值p/w的降序装包 分别以上面三种策略分别求以下情况背包问题的解: • n=7,M=15, 7 • ( p1 ,, p) =(10,5,15,7,6,18,3) • ( w1 ,, w7)=(2,3,5,7,1,4,1)
结果
The end,thank you!
请提问!
与其他算法比较
• 1.贪心法:处理问题的速度快,思想简单。使用该方法的 必要条件是寻找好的贪心法则。不足之处在于很多时候它 只能求的似优解,却不能求的最优解 • 2.动态规划法:可以求解最优解,重点在于徐兆最优决策 序列但是速度较慢。 • 3.分支限界法:可以求解最优解,重点在于寻找限界值。 易求最优解,但是空间花费较高,效率不是很高。 • பைடு நூலகம்择哪一种算法,不仅要根据问题本身还需要考虑到其他 因素,例如时间复杂度,空间复杂度,易求解等等因素。

贪心算法实现背包问题算法设计与分析实验报告

贪心算法实现背包问题算法设计与分析实验报告

算法设计与分析实验报告实验名称 贪心算法实现背包问题 评分 实验日期 年 月 日 指导教师 姓名 专业班级 学号一.实验要求1. 优化问题有n个输入,而它的解就由这n个输入满足某些事先给定的约束条件的某个子集组 成,而把满足约束条件的子集称为该问题的可行解。

可行解一般来说是不唯一的。

那些使目标函数取极值(极大或极小)的可行解,称为最优解。

2.贪心法求优化问题算法思想:在贪心算法中采用逐步构造最优解的方法。

在每个阶段,都作出一个看上去最优的决策(在一定的标准下)。

决策一旦作出,就不可再更改。

作出贪心决策的依据称为贪心准则(greedy criterion)。

3.一般方法1)根据题意,选取一种量度标准。

2)按这种量度标准对这n个输入排序3)依次选择输入量加入部分解中。

如果当前这个输入量的加入,不满足约束条件,则不把此输入加到这部分解中。

procedure GREEDY(A,n) /*贪心法一般控制流程*///A(1:n)包含n个输入//solutions←φ //将解向量solution初始化为空/for i←1 to n dox←SELECT(A)if FEASIBLE(solution,x)then solutions←UNION(solution,x)endifrepeatreturn(solution)end GREEDY4. 实现典型的贪心算法的编程与上机实验,验证算法的时间复杂性函数。

二.实验内容1. 编程实现背包问题贪心算法。

通过具体算法理解如何通过局部最优实现全局最优,并验证算法的时间复杂性。

2.输入5个的图的邻接矩阵,程序加入统计prim算法访问图的节点数和边数的语句。

3.将统计数与复杂性函数所计算比较次数比较,用表格列出比较结果,给出文字分析。

三.程序算法1. 背包问题的贪心算法procedure KNAPSACK(P,W,M,X,n)//P(1:n)和W(1;n)分别含有按P(i)/W(i)≥P(i+1)/W(i+1)排序的n件物品的效益值和重量。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

贪心算法实现01背包问题
算法思想:贪心原则为单位价值最大且重量最小,不超过背包最大承重量为约束条件。

也就是说,存在单位重量价值相等的两个包,则选取重量较小的那个背包。

具体实现过程是:首先可以设置一个备份pvu类型的数组,在不破环原数据的情况下,对此备份数组按单位重量价值从大到小的排序。

依次设立两个指针i,j(其中i表示当前应该参与最佳pv值的元素指针,j表示符合约束条件的指针(单位重量价值PV最大,重量最小,不超过最大承重量约束)
代码实现如下:
#include <iostream>
using namespace std;
typedef struct
{
int v;
int w;
float pv;
}pvu;
void sortByPv(pvu [],int );
int zeroneBags(pvu[],int,int,int * );
void print(pvu a[],int n)
{
for (int i=0;i<n;i++)
{
cout<<a[i].w<<" "<<a[i].v<<" "<<a[i].pv<<endl;
}
cout<<endl;
}
int main()
{
int i,maxw;
int w[]={1,2,3,2};
int v[]={9,10,15,6};
int n=sizeof(w)/sizeof(int );
const int N=n;
pvu arr[N];
for (i=0;i<n;i++)
{
arr[i].v=v[i];
arr[i].w=w[i];
arr[i].pv=v[i]*1.0/w[i];
}
int remained;
cout<<"输入背包的最大承重量:\n";
cin>>maxw;
cout<<"最大价值为:"<<zeroneBags(arr,n,maxw,&remained)<<"\n还剩"<<remained<<"公斤空间未使用"<<endl;
return 0;
}
void sortByPv(pvu arr[] ,int n)
{
pvu t;
int i,j;
for (i=0;i<n-1;i++)
for (j=0;j<n-1-i;j++)
if (arr[j].pv<arr[j+1].pv)
{
t=arr[j];
arr[j]=arr[j+1];
arr[j+1]=t;
}
}
int zeroneBags(pvu arr[],int n,int maxw,int *e)
{
int i=0,j,minw,totalv=0;
int avail=maxw;
sortByPv(arr,n); //按最大单位重量价值PV从大到小的排序
while (avail&&i<n)
{
minw=i;
for (j=0;j<n;j++)
if (arr[i].pv==arr[j].pv)
{
if (arr[i].w>arr[j].w&&j>i)
{
minw=j;
}
}
if (arr[minw].w<=avail)
{
avail-=arr[minw].w;
totalv+=arr[minw].v;
i++;
}
else
i++;
}
*e=avail;
return totalv; }
运行结果截图:。

相关文档
最新文档