背包问题(贪心算法)
贪心算法之背包问题

贪⼼算法之背包问题问题描述:给定n种物品,1个背包,背包容量为c,每个物品i的价值为vi,重量为wi,如何选择装⼊物品能使背包的总价值最⼤?注意:与0-1背包问题不同,在选择物品i装⼊背包时,可以选择物品i的⼀部分,⽽不⼀定要全部装⼊背包,1<=i<=n形式化描述:给定c >0, wi >0, vi >0 , 1≤i≤n.要求找⼀n元向量A=(x1,x2,…,xn), 0<=xi<=1【0~1表⽰取物品的某⼀部分】,1<=i<=n,使得 ∑wixi≤c【物品的重量和⼩于背包总容量】⽽且∑ vixi达到最⼤。
算法思路:将物品按照单位重量价值进⾏排序(从⼤到⼩),将尽可能多的单位重量价值最⾼的物品装⼊背包,若将这种物品全部装⼊背包后,背包还有多余容量,则选择单位重量价值次⾼的并尽可能多地装⼊背包。
如果最后⼀件物品⽆法全部装⼊,则计算可以装⼊的⽐例,然后按⽐例装⼊。
代码实现:数据结构:结构体1 #include <iostream>2 #include <algorithm>3using namespace std;4struct item{5int weight;//物品的重量6int value;//物品的价值7float bi;//物品单位重量的价值8float rate;//使⽤率:1代表物品完整放⼊,⼩于1代表被分割后放⼊9 }items[100];10bool cmp(const item &a,const item &b){11return a.bi>b.bi;12 }13int main(){14int n;//n件物品15float c;//背包容量为c16 cout<<"输⼊物品件数和背包容量:"<<endl;17 cin>>n>>c;18 cout<<"依次输⼊每件物品的价值和重量:"<<endl;19float v[n],w[n];//v[n]:n件物品的价值,w[n]:n件商品的重量20for(int i=0;i<n;i++){21 cin>>items[i].value>>items[i].weight;22 items[i].bi=items[i].value/items[i].weight;//计算单位重量价值23 items[i].rate=0;//初始化每件物品的使⽤率24 }25 sort(items,items+n,cmp);//按照单位重量的价值排序26int sum=0,j=0;27for(j=0;j<n;j++){28if(items[j].weight<=c){//选择单位价值重量最⼤的并且不超过背包容量的29 items[j].rate=1;30 sum+=items[j].weight;31 c-=items[j].weight;32 cout<<"重:"<<items[j].weight<<"、价值:"<<items[j].value<<"的物品被放⼊了背包"<<endl<<"放⼊⽐例:"<<items[j].rate<<endl;33 }34else break;35 }36if(j<n){//物品未装完37 items[j].rate=c/items[j].weight;//背包容量还剩c,计算出未装⼊的物品能装多少的⽐例38 sum+=items[j].rate*items[j].weight;//加上装⼊部分⽐例物品的重量39 cout<<"重:"<<items[j].weight<<"、价值:"<<items[j].value<<"被放⼊了背包"<<endl<<"放⼊⽐例:"<<items[j].rate<<endl;40 }41return0;424344 }。
贪心算法-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)计算时间。
背包问题解析(一)-贪心算法

背包问题解析(⼀)-贪⼼算法⼀、题⽬:有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)打印结果:四、算法分析:贪⼼选择是指所求问题的整体最优解可以通过⼀系列局部最优的选择,即贪⼼选择来达到。
贪心算法求连续背包问题

实验项目名称:贪心算法求连续背包问题一、实验目的:明确连续背包问题的概念;利用贪心算法解决连连续续背包问题;并通过本例熟悉贪心算法在程序设计中的应用方法。
二、实验原理: 贪心算法原理:在贪婪算法(greedy method )中采用逐步构造最优解的方法。
在每个阶段,都作出一个看上去最优的决策(在一定的标准下)。
决策一旦作出,就不可再更改。
作出贪婪决策的依据称为贪婪准则(greedy criterion )。
三、实验内容与步骤:贪心算法求连续背包问题问题描述:已知n 个物体和1个背包,其中物体i 有重量w i 和价值v i ,背包承重量为W 。
求一装载方案,要求在不超过背包负重的前提下,背包中装入的物品价值最大。
很明显,如果1ni i w W =≤∑,则最优解就是装入全部物体,因此下面假设1n i i w W =>∑。
注:连续背包问题中的物体可以任意分割,即部分装入背包。
分析:连续背包问题可形式化为如下模型:{}11max ..[0,1],1,,ni ii ni ii i x v x w W s t x i n ==⎧≤⎪⎨∈∈⎪⎩∑∑对于连续背包问题,可用贪心技术求得最优解。
贪心策略是单位重量价值高者优先。
例如:所给物体的重量和价值如下,则,程序可以得到如下结果:最大价值为163.0;所选各物体的数量为:1.0 1.0 1.0 0.8参考程序段如下//连续背包问题的贪心算法,最大单位重量价值优先//输入:各物体重量w 、价值v 和背包重量W ,已按v/w 降序排列#include<stdio.h>int knapsack(int n1,float w1[],float v1[],float W1){ int i; float weight; float x[10],s=0; for(i=1;i<=n1;i++) x[i]=0; weight=0; i=1;while(weight<W1) {if(weight+w1[i]<W1){x[i]=1;weight=weight+w1[i];}else{x[i]=(W1-weight)/w1[i];weight=W1;}i++;}for(i=1;i<=n1;i++) s=s+x[i]*v1[i];printf("背包所能容纳商品的最大价值为:%f\n",s);printf("所选择的商品的一个序列为:\n");for(i=1;i<=n1;i++)printf("%8.3f",x[i]);}void main(){int n,i,j;float w[10],v[10],W;clrscr();printf("输入商品数量n 和背包容量W:\n");scanf("%d,%f",&n,&W);printf("输入每件商品的重量,价值:\n");for(i=1;i<=n;i++)scanf("%f,%f",&w[i],&v[i]);knapsack(n,w,v,W);printf("\n");system("pause");}。
贪心算法实验(求解背包问题)

算法分析与设计实验报告第四次实验
}
}
输入较小的结果:
测试结
果
输入较大的结果:
附录:
完整代码(贪心法)
;
cout<<endl;
cout<<"待装物品的价值为:"<<endl;
for (i=0;i<n;i++)
cin>>item[i].v;
cout<<endl;
erval=item[i].v/item[i].w;
clock_t start,end,over; ;
实验心
得
首先这个实验,需要注意的点是背包问题与0-1背包不同,物品可以部分的放入背包中,所以思路也不一样,首先就是将物品按照单位质量价值排序,只这一点就有一点难度。
难度在于要是排序后物品的编号就会发生改变,输出的就不是之前的编号的物品,导致错误,后来发现如果为每一个物品保存一个副本,然后将它们的编号进行对比,就可以进行正确的输出了。
其中这个实验
让我学到了两点:一是结构体的使用,之前一直没有怎么用过,现在才发现自己其实不会用;二十对于库函数sort 函数的使用。
感觉每一次实验都有学到东西,很开心。
实验得
分 助教签名
sort(item,item+n,comparison); >c)
break;
tem[i]=1;
c-=item[i].w;
}
if(i<n) ;
for(i=0;i<n;i++) ==tmp[j])
x[j]=tem[i];
}
}
}。
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;}}运行结果(用列一)用列二上述结果显示:贪心算法不是总是最优的.动态规划与贪心算法比较;动态规划法又和贪婪算法有些一样,在动态规划中,可将一个问题的解决方案视为一系列决策的结果。
背包问题的贪心算法20页PPT文档

则用j比i好,∵装入A, V i 2 ;而装入B,Vi=3
对例。4.3的数据使用按效益值的非增次序的选择策略.
V 125,X 11 ,W 118 背包剩:C-18=2;物品2有次大效益值
(V2=24 )但w2=15,背包装不下物品2。使用 x2=2/15,刚好装满背
包
6
,且物品2的24/15 = v2/w2 较物品3的15/10= v3/w3效益值高。按 此选择策略,得②即(1, 2/15, 0),∑vixi=28.2 .此解是一个次优解。 显然,按物品效益值的非增次序装包不能得最优解。
背包问题:
与0-1背包问题类似,所不同的是在选择物品i装入背包时 ,可以选择物品i的一部分,而不一定要全部装入背包, 1≤i≤n。
这2类问题都具有最优子结构性质,极为相似,但背 包问题可以用贪心算法求解,而0-1背包问题却不能用 贪心算法求解。
2
例4.3 贪心算法不能求得0-1背包问题得最优解。
考虑背包问题: n=3,c=50kg,(v1,v2,v3)=(60,100,120), (w1,w2,w3)=(10,20,30). vi/wi=(6,5,4).贪心算法解是(1,1,0), ∑vixi=60+100 , ∑wixi=30;最优解是(0,1,1), ∑vixi=100+120, ∑wixi=50,
实际上,动态规划算法的确可以有效地解0-1背包问题。
3
4.2 背包问题
已知有n种物品和一个可容纳c重量的背包,每种物品i的
重量为wi。假定物品i的一部分放入背包会得到vixi的效益。其
中0≤xi≤1,vi>0 . 采用怎样的装包方法才会使装入背包物品的总
效益最大呢?即求解 n
背包问题的贪心算法

Wi Xi
16.5 20 20 20
Vi X i
24.25 28.2 31 31.5
先检验这四个为可行解*,即满足约束条件(4.2.2),(4.2.3).再比 较目标函数值,∑vixi .知④组解效益值最大.该组解是背包问题的最 优解。(见定理4.2)
6
例4.4 n=3,c=20, (V1,V2,V3) (25, 24,15) (W1,W2,W3) (18,15,10)
7
,且物品2的24/15 = v2/w2 较物品3的15/10= v3/w3效益值高。按 此选择策略,得②即(1, 2/15, 0),∑vixi=28.2 .此解是一个次优解。 显然,按物品效益值的非增次序装包不能得最优解。
原因:背包可用容量消耗过快。
(2)以容量作为量度。即按物品重量的非降次序将物
—选取最优的量度标准实为用贪心方法求解问题的核心.
16
4.3 贪心算法的基本要素
1.贪心选择性质
所谓贪心选择性质是指所求问题的整体最优解可以 通过一系列局部最优的选择,即贪心选择来达到。这 是贪心算法可行的第一个基本要素,也是贪心算法与 动态规划算法的主要区别。
动态规划算法通常以自底向上的方式解各子问 题,而贪心算法则通常以自顶向下的方式进行,以迭 代的方式作出相继的贪心选择,每作一次贪心选择就 将所求问题简化为规模更小的子问题。
品装包。如例4.4中的解③(让背包尽可能慢被消耗)
排序 : (w3,w2,w1)= (10,15,18)
(V3,V2,V1) (15, 24, 25)
V3=15,x3=1,w3=10,背包剩余C-10=10;物品2有次大重量(w2=15), 但包装不下。使用x2=2/3,刚好装满背包且物品2装入2/3与物品1 装入5/9的容量均为10个单位。但前者的效益值24×2/3=16 >后者
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
算法分析与设计实验报告
第 4 次实验
}
附录:完整代码
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
struct node{
float value;
float weight;
};
float Value,curvalue=0;
float Weight,curweight=0;
//按价重比冒泡排序
void sort(node Node[],int M){
int i,j;
node temp;
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;
}
}
}
printf("物品的价重比从高到低依次排列为:\n");
for(i=0;i<M;i++){
printf("%.2f ",Node[i].value);
}
printf("\n");
for(i=0;i<M;i++){
printf("%.2f ",Node[i].weight);
}
}
//装包主要方法及输出
void pack(node Node[],int M){
int i,j=1;
printf("\n\n选中物品的价格为:\n");
for(i=0;i<M;i++){
if((Node[i].weight+curweight)<=Weight){
curvalue+=Node[i].value;
curweight+=Node[i].weight;
printf("第j次选择为:%.2f \n",curvalue); j++;
}
}
}
int main(){
int i,M;
printf("\n请输入背包容积:");
scanf("%f",&Weight);
printf("\n请输入物品个数:");
scanf("%d",&M);
node Node[M];
srand(time==NULL);
for(i=0;i<M;i++){
Node[i].weight=rand()%10;
Node[i].value=rand()%10;
}
sort(Node,M);
pack(Node,M);
return 0;
}。