贪心法 求解背包问题
贪心算法之背包问题
贪⼼算法之背包问题问题描述:给定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)计算时间。
贪心算法补充背包问题
void Insertionsort(goodinfo goods[],int n) {//插入排序,按pi/wi价值收益进行排序,一般教材 {//插入排序 插入排序, pi/wi价值收益进行排序 价值收益进行排序, 上按冒泡排序 int j,i; for(j=2;j<=n;j++) { goods[0]=goods[j]; i=j-1; i=jwhile (goods[0].p>goods[i].p) { goods[i+1]=goods[i]; i--; --; } goods[i+1]=goods[0]; } }//按物品效益,重量比值做升序排列 }//按物品效益 按物品效益,
引言
顾名思义,贪心算法总是作出在当前看来 顾名思义,贪心算法总是作出在当前看来 最好的选择。也就是说贪心算法并不从整 体最优考虑,它所作出的选择只是在某种 意义上的局部最优选择。当然,希望贪心 意义上的局部最优选择。当然,希望贪心 算法得到的最终结果也是整体最优的。虽 然贪心算法不能对所有问题都得到整体最 优解,但对许多问题它能产生整体最优解。 如单源最短路经问题,最小生成树问题等。 在一些情况下,即使贪心算法不能得到整 体最优解,其最终结果却是最优解的很好 近似。
Hale Waihona Puke 贪心算法解决背包问题的算法实现: 贪心算法解决背包问题的算法实现:
#include <iostream.h> struct goodinfo { float p; //物品效益 float w; //物品重量 float X; //物品该放的 数量 int flag; //物品编号 };//物品信息结构体
贪心算法解决背包问题有几种策略: 贪心算法解决背包问题有几种策略: (i) 一种贪婪准则为:从剩余的物品中,选出可以装入背包的价值最 大的物品,利用这种规则,价值最大的物品首先被装入(假设有足够 容量),然后是下一个价值最大的物品,如此继续下去。这种策略不 能保证得到最优解。例如,考虑n=2, w=[100,10,10], p =[20,15,15], 能保证得到最优解。例如,考虑n=2, c = 105。当利用价值贪婪准则时,获得的解为x= [ 1 , 0 , 0 ],这 105。当利用价值贪婪准则时,获得的解为x= ],这 种方案的总价值为2 0。而最优解为[ 种方案的总价值为2 0。而最优解为[ 0 , 1 , 1 ],其总价值为3 0。 ],其总价值为3 0。 (ii) 另一种方案是重量贪婪准则是:从剩下的物品中选择可装入背包 的重量最小的物品。虽然这种规则对于前面的例子能产生最优解,但 在一般情况下则不一定能得到最优解。考虑n= 在一般情况下则不一定能得到最优解。考虑n= 2 ,w=[10,20], p=[5,100], c= 2 5。当利用重量贪婪策略时,获得的解为x =[1,0], 5。当利用重量贪婪策略时,获得的解为x 比最优解[ 比最优解[ 0 , 1 ]要差。 ]要差。 (iii) 还有一种贪婪准则,就是我们教材上提到的,认为,每一项计 算yi=vi/si,即该项值和大小的比,再按比值的降序来排序,从第一项 yi=vi/si,即该项值和大小的比,再按比值的降序来排序,从第一项 开始装背包,然后是第二项,依次类推,尽可能的多放,直到装满背 包。 有的参考资料也称为价值密度pi/wi贪婪算法。这种策略也不能保证得 有的参考资料也称为价值密度pi/wi贪婪算法。这种策略也不能保证得 到最优解。利用此策略试解n= 到最优解。利用此策略试解n= 3 ,w=[20,15,15], p=[40,25,25], c=30 时的最优解。虽然按pi /wi 非递(增)减的次序装入物品不能 时的最优解。虽然按pi 保证得到最优解,但它是一个直觉上近似的解。 而且这是解决普通背包问题的最优解,因为在选择物品i 而且这是解决普通背包问题的最优解,因为在选择物品i装入背包时, 可以选择物品i的一部分,而不一定要全部装入背包,1≤i≤n。 可以选择物品i的一部分,而不一定要全部装入背包,1≤i≤n。
背包问题解析(一)-贪心算法
背包问题解析(⼀)-贪⼼算法⼀、题⽬:有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背包问题
贪心法的关键是度量标准,这个程序的度量标准有三个占用空间最小物品效益最大物品效益/占用空间最大程序实现如下:至于文件的操作不加论述。
#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;}。
贪心法解决背包问题
算法分析实验报告贪心法解决背包问题学生姓名:专业:班级:学号:指导教师:2017年6月12日目录一、实验题目 (2)二、实验目的 (2)三、实验要求 (2)四、实现过程 (3)1、实验设计: (3)2、调试分析 (5)3、运行结果: (6)4、实验总结: (6)五、参考文献 (6)一、实验题目贪心法解决背包问题二、实验目的1)以背包问题为例,掌握贪心法的基本设计策略。
2)熟练掌握各种贪心策略情况下的背包问题的算法并实现;其中:量度标准分别取:效益增量v、物品重量w、v/ w比值;3) 分析实验结果来验证理解贪心法中目标函数设计的重要性。
三、实验要求1.[问题描述]:给定n种物品和一个背包。
物品i的重量是Wi,其价值为Vi,背包的容量为C。
应如何选择装入背包的物品,使得装入背包中物品的总价值最大? 与0-1背包问题类似,所不同的是在选择物品i装入背包时,可以选择物品i的一部分,而不一定要全部装入背包,但不可以重复装入。
2.[算法]:贪心法的基本思路:从问题的某一个初始解出发逐步逼近给定的目标,以尽可能快的地求得更好的解。
当达到某算法中的某一步不能再继续前进时,算法停止。
该算法存在问题:1)不能保证求得的最后解是最佳的;2)不能用来求最大或最小解问题;3)只能求满足某些约束条件的可行解的范围。
四、实现过程1、实验设计:1.用贪心法求解背包问题的关键是如何选定贪心策略,使得按照一定的顺序选择每个物品,并尽可能的装入背包,直至背包装满。
至少有三种看似合理的贪心策略:1)按物品价值v降序装包,因为这可以尽可能快的增加背包的总价值。
但是,虽然每一步选择获得了背包价值的极大增长,但背包容量却可能消耗太快,使得装入背包得物品个数减少,从而不能保证目标函数达到最大。
2)按物品重量w升序装包,因为这可以装入尽可能多的物品,从而增加背包总价值。
但是,虽然每一步选择使背包得容量消耗得慢了,但背包价值却没能保证迅速增长,从而不能保证目标函数达到最大。
背包问题的贪心算法
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 >后者
算法设计和分析实验四:贪心算法求解背包问题
实验五:贪心算法求解背包问题实验内容应用贪心算法求解离散背包问题,分析时间复杂度。
有一个承重为W的背包和n个物品,它们各自的重量和价值分别是wi和vi (1<=i<=n),设求这些物品中最有价值的一个子集。
如果每次选择某一个物品的时候,只能全部拿走,则这一问题称为离散(0-1)背包问题;如果每次可以拿走某一物品的任意一部分,则这一问题称为连续背包问题。
算法思想•动态规划的思想:–对较小的子问题进行一次求解,并把结果记录下来,然后利用较小问题的解,求解出较大问题的解,直到求解出最大问题的解。
–引进一个二维数组ch[MAX][MAX],用ch[i][j]记录CH1与CH2的LCS的长度,b[i][j]记录ch[i][j]是通过哪一个子问题的值求得的,以决定搜索的方向。
我们是自底向上进行递推计算,那么在计算ch[i,j]之前,ch[i-1][j-1],ch[i-1][j]与ch[i][j-1]均已计算出来。
此时我们根据CH1 [i] = CH2[j]还是CH1[i] !=CH2[j],就可以计算出ch[i][j]。
算法length(string CH1,string CH2,int b[MAX][MAX])//用于构建动态数组//输入:两字符窜//输出:最长公共子序列for(i=1;i<=ch1Len;i++)//二重循环求解for(int j=1;j<=ch2Len;j++){if(CH1[i-1]==CH2[j-1])//相等字符{ch[i][j]=ch[i-1][j-1]+1;b[i][j]=0;}else if(ch[i-1][j]>=ch[i][j-1])//上比较大{ch[i][j]=ch[i-1][j];b[i][j]=1;}else//左比较大{ch[i][j]=ch[i][j-1];b[i][j]=-1;}}printCS(int b[MAX][MAX],string x,int i,int j) //回溯求出最长子序列输出//输入:标记数组//输出:最长子序列if(i == 0 || j == 0)//边界,返回return;if(b[i][j] == 0){printCS(b, x, i-1, j-1);//左上cout<<x[i-1]<<" ";}else if(b[i][j] == 1)printCS(b, x, i-1, j);//上elseprintCS(b, x, i, j-1);//左源程序//应用贪心算法求解离散背包问题#include<iostream>using namespace std;#define MAX 100//结构体struct Elem{double W;double V;double P;int number;};//顺序表struct SqList{Elem *elem;int length;int listsize;};//构造一个空的线性顺序表void InitList_Sq(SqList &L){L.elem=(Elem *)malloc(100*sizeof(Elem)); L.length=0;L.listsize=100;}//******************************** //构造背包,顺序表//******************************void input(SqList &L){cout<<"请输入物品的个数:";cin>>L.length;for(int i=0;i<L.length;i++){cout<<"请输入第"<<i+1<<"个物品的重量和价值:";cin>>L.elem[i].W>>L.elem[i].V;L.elem[i].P=L.elem[i].V/L.elem[i].W;cout<<"价值比为:"<<L.elem[i].P<<endl;L.elem[i].number=i+1;}}//*********************************//插入排序由大到小//*******************************void inser(SqList &L){Elem inserter;int index;//inserter待插入合适位置的元素,index指示插入位置for(int pass=1;pass<L.length;pass++){//共比较size-1轮inserter=L.elem[pass];//第pass轮时,待插入的对象是a[pass] index=pass-1;while(index>=0&&inserter.P>L.elem[index].P){ //寻找插入位置L.elem[index+1]=L.elem[index];index--;//指针前移,再比较}L.elem[index+1]=inserter;//跳出while时,找到插入位置}//end of forcout<<"按照价值比由大到小排列的顺序为:";for(pass=0;pass<L.length;pass++)cout<<L.elem[pass].number<<" ";cout<<endl;}//*************************************************8 //背包程序//采用贪心算法//根据价值和重量的比来实现贪心算法//************************************************ void bag(SqList L){double w,sumV=0,sumW=0;int list[MAX],a=0;cout<<"请输入背包承重量W:";cin>>w;inser(L);for(int i=0;i<L.length;i++){while(sumW+L.elem[i].W<=w){sumW=sumW+L.elem[i].W;sumV=sumV+L.elem[i].V;list[a++]=L.elem[i].number;}}cout<<"最后包里的总重量为:"<<sumW<<endl; cout<<"最后包里的总价值为:"<<sumV<<endl; cout<<"放到背包中的物品的序号列表为:"; for(i=0;i<a;i++){cout<<list[i]<<" ";}}int main(){cout<<"贪心算法求解背包问题"<<endl;SqList L;InitList_Sq(L);input(L);bag(L);return 0;}实验结论1、运行截图查找最长公共子序列长度时的动态规划两个for循环,时间复杂度为O(n*n)。
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 ,还真不如随便放⼊点棉花进去合算。
所以总是放铁球进去,不考虑是否放⼊棉花,容易产⽣闲置空间,最终会得不到最优选择,可能只是最优选择的近似选择。
现在再次回到背包问题上,要使得背包中可以获得最⼤总价值的物品,参照铁球的例⼦我们可以知道选择单位重量下价值最⾼的物品放⼊为最优选择。
但是由于物品不可分割,⽆法保证能将背包刚好装满,最后闲置的容量⽆法将单位重量价值更⾼的物品放⼊,此时要是可以将单位重量价值相对低的物品放⼊,反⽽会让背包的总价值和单位重量的价值更⾼。
贪心算法与背包问题的求解策略
贪心算法与背包问题的求解策略贪心算法是一种常用的优化算法,特别适用于一些具有最优子结构性质的问题。
而背包问题是一个经典的组合优化问题,它涉及到在限定容量下如何选择物品,使得总价值最大化。
本文将探讨贪心算法在背包问题求解中的应用策略。
一、背包问题的定义与分类背包问题是在给定容量的背包和一组物品的情况下,如何选择物品放入背包中,使得物品的总价值最大化。
背包问题可以分为0-1背包问题、分数背包问题和多重背包问题三种。
1. 0-1背包问题:每种物品只能选择放入背包一次或者不放入。
目标是使得背包中物品价值最大化。
2. 分数背包问题:物品可以分割成较小的部分放入背包,即可以选择部分物品放入。
目标是使得背包中物品价值最大化。
3. 多重背包问题:物品有多个可选的数量限制,每种物品可以选择放入多次但不能超过其数量限制。
目标是使得背包中物品价值最大化。
二、贪心算法在背包问题求解中的应用策略在求解背包问题时,贪心算法通常采取以下两种策略:1. 价值密度优先策略:对于0-1背包问题和分数背包问题,贪心算法可以根据物品的单位价值(价值与重量的比率)进行排序,然后按照价值密度从大到小的顺序选择物品放入背包。
这样可以保证每次选择的物品是当前局部最优解,进而得到全局最优解。
算法步骤如下:a) 计算每种物品的单位价值。
b) 对物品按照单位价值进行排序。
c) 从价值最大的物品开始,依次尝试放入背包直至放满或无法继续放入。
2. 数量优先策略:对于多重背包问题,贪心算法可以根据物品的剩余数量进行排序,优先选择剩余数量最多的物品。
这样可以尽可能多地选择该物品,以使总价值最大化。
算法步骤如下:a) 对物品按照剩余数量进行排序。
b) 从剩余数量最多的物品开始,依次尝试放入背包直至放满或无法继续放入。
值得注意的是,贪心算法在某些情况下可能无法得到最优解。
对于一些特殊的背包问题,如存在约束条件或物品具有特殊属性时,贪心算法可能会得出次优解或错误解。
贪心法求解背包问题
问题描述
•
已知有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.分支限界法:可以求解最优解,重点在于寻找限界值。 易求最优解,但是空间花费较高,效率不是很高。 • பைடு நூலகம்择哪一种算法,不仅要根据问题本身还需要考虑到其他 因素,例如时间复杂度,空间复杂度,易求解等等因素。
贪心算法求解背包问题C语言描述
贪心算法求解背包问题:#include<stdio.h>#define maxnumber 20typedef struct node{float w;float v;int i;}Object;float find(Object wp[],int n,float M) {float x[maxnumber];int i;float maxprice=0;for(i=1;i<=n;i++)//初始化x[n];{x[i]=0.0;}i=0;while(wp[i].w < M){x[wp[i].i]=1;M=M-wp[i].w;i++;}x[wp[i].i]=M/wp[i].w;//输出解向量printf("解向量是:\n");for(i=1;i<=n;i++){printf("x[%d]=%f",i,x[i]);}printf("\n");//计算最大价值for(i=0;i<n;i++){maxprice=maxprice+wp[i].v*x[wp[i].i];}return maxprice;}void main(){Object wp[maxnumber];int i,j,n;float C;//背包的重量int flag;float maxprice,temp;printf("请输入物品的种数:");scanf("%d",&n);printf("请输入背包的重量:");scanf("%f",&C);printf("\n请输入物品的序号、重量和价值:");for(i=0;i<n;i++){scanf("%d",&wp[i].i);scanf("%f",&wp[i].w);scanf("%f",&wp[i].v);}printf("\n输入的物品是:\n");//输出物品for(i=0;i<n;i++){printf(" %d",wp[i].i);printf(" %f",wp[i].w);printf(" %f",wp[i].v);printf("\n");}//用冒泡排序对物品按照单位价值进行降序排序for(i=1;i<n;i++){flag=0;for(j=n-1;j>=i;j--){if(wp[j-1].v/wp[j-1].w < wp[j].v/wp[j].w){temp=wp[j-1].i;wp[j-1].i=wp[j].i;wp[j].i=temp;temp=wp[j-1].w;wp[j-1].w=wp[j].w;wp[j].w=temp;temp=wp[j-1].v;wp[j-1].v=wp[j].v;wp[j].v=temp;flag=1;}if(flag==0)break;}}printf("\n排序后的物品是:\n");//输出物品for(i=0;i<n;i++){printf(" %d",wp[i].i);printf(" %f",wp[i].w);printf(" %f",wp[i].v);printf("\n");}maxprice=find(wp,n,C);printf("\n物品的重价值为:%f",maxprice);}。
基于朴素贪心算法的背包问题解决方案
基于朴素贪心算法的背包问题解决方案背包问题是一类经典的组合优化问题,它的一般形式描述为:有一个固定大小的背包,和一些物品,每个物品都有自己的价值和大小,需要选出一些物品装入背包中,使得装进去的物品价值最大化,同时又不能超出背包容量的限制。
这个问题在实际生活中有很多应用,比如在货物的装载和运输、在零售商的库存管理、在网页推荐系统等等。
解决背包问题的方法有很多,其中比较经典的是基于动态规划的解法,但是这种解法需要使用大量的存储空间,如果物品数量很大的话,计算复杂度也会很高。
因此本文将介绍一种基于朴素贪心算法的背包问题解决方案。
一、背包问题的数学模型在介绍具体的解决方案之前,我们需要先来看一下背包问题的数学模型。
假设我们有n个物品,第i个物品的重量为wi,价值为vi,背包的容量为W。
那么背包问题可以用下面的数学模型来描述:$$\begin{aligned}&\max\sum_{i=1}^{n}v_ix_i\\&s.t.\sum_{i=1}^ {n}w_ix_i\leq W\\&x_i\in \{0,1\}\end{aligned}$$其中,$x_i$表示第$i$个物品是否被选中,$v_i$和$w_i$分别表示第$i$个物品的价值和重量。
第一个约束条件表示所有选中的物品的总重量不能超过背包的容量$W$,第二个约束条件表示每个物品最多只能选一次。
二、基于朴素贪心算法的解法朴素贪心算法的思路很简单:每次选择可行的物品中价值最大的那一个,直到不能再选为止。
对于背包问题来说,我们可以按照物品的单位价值(即价值与重量比值)从大到小排序,然后依次选择可行的物品加入背包中。
具体步骤如下:1. 计算每个物品的单位价值,按照单位价值从大到小排序。
2. 依次加入可行的物品,直到不能再加入为止。
3. 最后得到的物品组合就是背包问题的最优解。
该算法的时间复杂度为$O(nlogn)$,其中$n$为物品的数量。
贪心算法实现背包问题算法设计与分析实验报告
算法设计与分析实验报告实验名称 贪心算法实现背包问题 评分 实验日期 年 月 日 指导教师 姓名 专业班级 学号一.实验要求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件物品的效益值和重量。
2贪心算法解决部分背包问题
2贪心算法解决部分背包问题一、实验目的学习掌贪心算法法思想。
二、实验内容用贪心法解决部分背包问题。
给定n种物品和一个背包。
物品i的重量是Wi,其价值为pi,背包的容量为M,将物品i的一部分xi放入背包会得到pi xi的效益。
应如何选择装入背包的物品,使得装入背包中物品的总价值最大?给出具体的装包方案。
在选择装入背包的物品时,对每种物品i,可以整件装入背包、不装入背包或部分装入背包。
但不能将物品i装入背包多次。
四、需求分析对于给定n种物品和一背包。
在容量最大值固定的情况下,要求装入的物品价值最大化。
五、基本思想:贪婪法是解决最优化问题时的一种简单但适用范围有限的策略。
总是对当前的问题作最好的选择,也就是局部寻优。
最后得到整体最优。
总是选择单位价值最高的物品。
六、详细设计#include<iostream>using namespace std;struct _Object//物品结构体{int Value;//物品价值int Weight;//物品重量int AveValue;//物品单位价值float Num;//物品可以放入的数量void knaspsack(int n,float M,_Object object[]){ //n为物品个数,M为背包容量int i;float C=M;for(i=0;i<n;i++){object[i].Num=0;//初始化放入背包的物品为0if(object[i].Weight>C)break;//当物品重量大于背包容量时else//小于时{object[i].Num=1;//物品i放入一件C-=object[i].Weight;//背包容量减小}}if(i<=n)//当不能放入整个物品时,选取物品一部分放入object[i].Num=C/object[i].Weight;for(i=0;i<n;i++){if(object[i].Num>0)cout<<"重量为: "<<object[i].Weight<<" 价值为: "<<object[i].Value<<" 的物品放入"<<object[i].Num<<" 件"<<endl;}}void SortObject(_Object object[],int n)//将各个物品按单位价值进行排序{int j;_Object temp;int i;for(i=0;i<n;i++)object[i].AveValue=object[i].Value/object[i].Weight;//各个物品的单位价值for(i=0;i<n-1;i++)//根据物品的单位价值对物品进行从大到小的冒泡排序{for(j=0;j<n-i-1;j++){if(object[j].AveValue<object[j+1].AveValue){temp=object[j];object[j]=object[j+1];object[j+1]=temp;}}}}int main(){_Object object[4];//4个物品int M=9;//背包容量为15object[0].Weight=2;object[0].Value=3;object[1].Weight=3;object[1].Value=4;object[2].Weight=4;object[2].Value=5;object[3].Weight=5;object[3].Value=7;SortObject(object,4);knaspsack(4,M,object);}七、结果分析:对于0-1背包问题,贪心算法之所以不能得到最优解是因为在这种情况下,它无法保证最后能将背包装满,部分闲置的背包空间,使每公斤背包的价值降低了。
贪心算法与背包问题的求解策略
贪心算法与背包问题的求解策略贪心算法(Greedy Algorithm)是一种常用的算法策略,用于求解最优化问题。
背包问题(Knapsack Problem)则是一个经典的组合优化问题,涉及在限制条件下如何选择物品以最大化价值。
本文将探讨贪心算法在解决背包问题时的应用与求解策略。
一、背包问题简介背包问题是一个常见的动态规划问题,其基本形式为:有一个背包,容量为C(常为非负整数),有n个物品,每个物品的重量为w[i],价值为v[i]。
现在需要从这些物品中选择一部分装入背包,使得在满足背包容量的限制下,所装入物品的总价值最大化。
二、贪心算法的基本思想贪心算法的基本思想是,每一步都选择当前情况下的最优解,希望通过每一步的最优解最终达到全局最优解。
然而,贪心算法并不是适用于所有问题的通用解决方法,它适用于一些特定的问题,如背包问题。
三、贪心算法在背包问题中的应用在背包问题中,常见的贪心策略有两种:按价值密度排序和按重量排序。
下面将分别介绍这两种贪心策略的具体应用。
1. 按价值密度排序按价值密度排序是指将物品按照单位重量的价值从大到小进行排序。
具体操作步骤如下:(1)计算每个物品的价值密度,即v[i]/w[i]。
(2)按照价值密度从大到小的顺序对物品进行排序。
(3)从价值密度最高的物品开始,依次将物品放入背包,直至背包容量达到上限或无物品可放。
2. 按重量排序按重量排序是指将物品按照重量从小到大进行排序。
具体操作步骤如下:(1)按照物品的重量从小到大进行排序。
(2)从重量最小的物品开始,依次将物品放入背包,直至背包容量达到上限或无物品可放。
四、贪心算法的优缺点贪心算法相比其他算法具有简单、高效的特点。
然而,贪心算法并不是万能的,它在某些情况下可能无法得到最优解。
例如,在背包问题中,贪心算法按照价值密度排序的策略并不能保证一定能得到最优解,因为可能存在某些物品的价值密度很高,但重量也很大,无法放入背包。
五、贪心算法的应用场景贪心算法常被应用于一些特定的问题领域,如最小生成树、调度问题、图着色等。
背包问题贪心法和动态规划方案法求解
背包问题贪心法和动态规划方案法求解嘿,大家好!今天咱们来聊聊那个让人又爱又恨的背包问题。
这个问题可是算法领域的经典难题,不过别怕,今天我会用贪心法和动态规划两种方法帮你轻松搞定它!来个简单直接的背景介绍。
背包问题,简单来说,就是给定一组物品,每个物品都有一定的价值和重量,你需要在不超过背包承载重量的前提下,挑选出价值最大的物品组合。
听起来是不是有点像生活中的购物决策?哈哈,没错,这就是背包问题的魅力所在。
好,下面咱们直接进入主题。
一、贪心法贪心法,顾名思义,就是每一步都选择当前看起来最优的方案。
对于背包问题,贪心法的核心思想就是:每次都选取价值密度最大的物品。
1.计算每个物品的价值密度,即价值除以重量。
2.然后,按照价值密度从大到小排序。
3.从排序后的列表中依次选取物品,直到背包装满或者没有物品可选。
二、动态规划法动态规划,这是一种更加严谨、也更复杂的方法。
它的核心思想是:通过把大问题分解成小问题,逐步求解,最终得到最优解。
1.定义一个二维数组dp[i][j],表示在前i个物品中选择,背包容量为j时的最大价值。
2.我们考虑第i个物品是否放入背包。
如果放入,则前i-1个物品在容量为j-w[i]时的最大价值加上w[i]的价值,即dp[i][j]=dp[i-1][j-w[i]]+w[i]。
如果不放入,则前i-1个物品在容量为j时的最大价值,即dp[i][j]=dp[i-1][j]。
3.通过比较这两种情况,取最大值作为dp[i][j]的值。
整个过程中,我们需要遍历所有物品和所有可能的背包容量,最终得到dp[n][W]就是我们要找的最大价值。
现在,让我们用一段代码来具体实现一下动态规划法:defknapsack(W,weights,values):n=len(values)dp=[[0for_inrange(W+1)]for_inrange(n+1)]foriinrange(1,n+1):forjinrange(1,W+1):ifj>=weights[i-1]:dp[i][j]=max(dp[i-1][j],dp[i-1][j-weights[i-1]]+values[i -1])else:dp[i][j]=dp[i-1][j]returndp[n][W]测试数据W=50weights=[10,20,30]values=[60,100,120]print(knapsack(W,weights,values))怎么样?是不是觉得动态规划法虽然复杂,但逻辑清晰,更容易找到最优解?通过上面的分析,我们可以看到,贪心法简单高效,但有时候并不能得到最优解;而动态规划法虽然计算复杂度较高,但可以得到最优解。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验三:贪心法求解背包问题一、实验目的与要求1、掌握背包问题的算法2、初步掌握贪心算法二、实验题问题描述:与0-1背包问题相似,给定n种物品和一个背包。
物品i的重量是wi,其价值为vi,背包的容量为c。
与0-1背包问题不同的是,在选择物品i装入背包时,背包问题的解决可以选择物品i的一部分,而不一定要全部装入背包,1< i < n。
三、实验代码package xp3;import java.awt.*;import java.awt.event.*;import javax.swing.*;public class Greedy extends JFrame {private static final long serialVersionUID= -1508220487443708466L;private static final int width = 360;// 面板的宽度private static final int height = 300;// 面板的高度public int M;public int[] w;public int[] p;public int length;Greedy() {// 初始Frame参数设置this.setTitle("贪心算法");setDefaultCloseOperation(EXIT_ON_CLOSE);setSize(width, height);Container c = getContentPane();c.setLayout(new BoxLayout(c, BoxLayout.Y_AXIS));setLocation(350, 150);// 声明一些字体样式Font topF1 = new Font("宋体", Font.BOLD, 28);Font black15 = new Font("宋体", Font.PLAIN, 20);Font bold10 = new Font("宋体", Font.BOLD, 15);// 声明工具栏及属性设置JPanel barPanel = new JPanel();JMenuBar topBar = new JMenuBar();topBar.setLocation(1, 1);barPanel.add(topBar);// 面板1和顶部标签属性设置JPanel p1 = new JPanel();JLabel topLabel = new JLabel("背包问题");topLabel.setForeground(Color.blue);topLabel.setFont(topF1);p1.add(topLabel);// 中间面板和标签及输入框属性设置JPanel p2 = new JPanel();p2.setLayout(new BoxLayout(p2, BoxLayout.Y_AXIS));JLabel wLabel = new JLabel("重量:");JLabel pLabel = new JLabel("效益:");wLabel.setFont(black15);pLabel.setFont(black15);//final JTextField wText = new JTextField(8);final JTextField pText = new JTextField(8);p2.add(wLabel);p2.add(wText);p2.add(pLabel);p2.add(pText);//// 中下部面板和标签属性设置JPanel p3 = new JPanel();JLabel bottomLabel = new JLabel("注意:输入多个时请添加分割符‘,’"); bottomLabel.setFont(bold10);bottomLabel.setForeground(Color.red);bottomLabel.setHorizontalAlignment(SwingConstants.RIGHT);p3.add(bottomLabel);JPanel p5 = new JPanel();p5.setLayout(new BoxLayout(p5, BoxLayout.Y_AXIS));JLabel mLabel = new JLabel(" 背包总重量:");mLabel.setFont(black15);final JTextField mText = new JTextField(8);p5.add(mLabel);p5.add(mText);// 面板和按钮的设置JPanel p4 = new JPanel();JButton submit = new JButton("确定");submit.addActionListener(new ActionListener() {public void actionPerformed(ActionEvent e) {String s1 = pText.getText(); //效益String s2 = wText.getText(); //重量String s3 = mText.getText(); //背包System.out.println(s1);System.out.println(s2);System.out.println(s3);String s1Copy,s2Copy,s3Copy;s1Copy = s1;s2Copy = s2;s3Copy = s3;s1Copy = s1Copy.replaceAll(",","");s2Copy = s2Copy.replaceAll(",","");s3Copy = s3Copy.replaceAll(",","");System.out.println(s1Copy);System.out.println(s2Copy);System.out.println(s3Copy);try{String[] temp = s1.split(",");// 按照‘,’分割字符串p = new int[temp.length];for (int i = 0; i < temp.length; i++)p[i] = Integer.parseInt(temp[i]);//temp = s2.split(",");w = new int[temp.length];for (int i = 0; i < temp.length; i++) w[i] =Integer.parseInt(temp[i]);//if (w.length == p.length){length = w.length;}else {JOptionPane.showMessageDialog(null, "长度不等,检查后重新输入!"); }M = Integer.parseInt(s3);}catch(NumberFormatException e2){e2.printStackTrace();try {i f (s2.equals("")){JOptionPane.showMessageDialog(null, "重量不能为空!");return;}else{if (s1.equals("")){JOptionPane.showMessageDialog(null, "效益值不能为空!");return;}else{if (s3.equals(""))JOptionPane.showMessageDialog(null, "总重量不能为空!");return;}}} catch (Exception e3) {// TODO: handle exception}}//可以执行贪心算法了int [] wCopy = new int [w.length];int [] pCopy = new int [w.length];float temp2;int temp1;float totalx=0;float [] x = new float [w.length];//效益和重量的比值float [] n =new float[w.length];//记录个数float [] nCopy = new float[w.length];for(int i=0;i<w.length;i++){wCopy [i] = w[i];pCopy [i] = p[i];}for (int i=0;i<w.length;i++)x[i] = (float) ((p[i]*1.0)/w[i]);for(int i= 0;i<w.length;i++)for(int j=i+1;j<w.length;j++){if(x[i] < x[j]){temp2 = x[j];x[j] = x[i];x[i] =temp2;temp1 = p[j];p[j] = p[i];p[i] = temp1;temp1 = w[j];w[j] = w[i];w[i] = temp1;}}//效益重量比值排序Backpack b = new Backpack(M,w,p,n);for(int i=0;i<w.length;i++)for(int j=0;j<w.length;j++){if(wCopy[i]==w[j] && pCopy[i]==p[j]){nCopy[i] = b.n[i];}}for(int j = 0;j<w.length;j++)totalx=totalx+n[j]*p[j];ShowResult s = new ShowResult(p,w,length,n,totalx); }//actionPerformed});p4.add(submit);// p4.add(eButton);//JPanel topPanel = new JPanel();topPanel.setLayout(new BoxLayout(topPanel, BoxLayout.Y_AXIS));topPanel.add(p1);topPanel.add(p2);topPanel.add(p5);topPanel.add(p3);topPanel.add(p4);c.add(barPanel);c.add(topPanel);setVisible(true);}// 构造方法p ublic static void main(String [] args){Greedy g = new Greedy();}//end main}c lass Backpack{private int capacity;int length ;//数组元素个数float [] n;public Backpack(int M,int [] w,int [] p,float [] n){ this.capacity = M;this.length = w.length;this.n = n;int i;for(i = 0;i<length;i++){if(w[i]>capacity) break;else {n[i] = 1;capacity = capacity-w[i];}}//end forif(i<length)n[i] = (float) ((capacity*1.0)/w[i]);}//构造方法}c lass ShowResult extends JFrame{private static final long serialVersionUID = 6592095135353992914L;ShowResult(int[] p,int[] w,int length,float[] n,float totalx){ setDefaultCloseOperation(DISPOSE_ON_CLOSE);Container c = getContentPane();c.setLayout(new BoxLayout(c,BoxLayout.Y_AXIS));setSize(360,300);setLocation(400,200);setTitle("最后结果");java.text.DecimalFormat df=newjava.text.DecimalFormat("#.##");String ps = null;String ws = null;String ns = null;ps = Integer.toString(p[0])+",";ws = Integer.toString(w[0])+",";ns = Float.toString(n[0])+"个,";//格式化小数部分for(int j =0;j<n.length;j++){n[j] = Float.parseFloat(df.format(n[j]));}for(int i =1;i<w.length;i++){ps = ps+Integer.toString(p[i])+",";ws = ws+Integer.toString(w[i])+",";ns = ns+Float.toString(n[i])+"个,";}JPanel p1 = new JPanel();p1.setLayout(new BoxLayout(p1,BoxLayout.Y_AXIS));JLabel wLabel = new JLabel("重量值分别是:");JLabel pLabel = new JLabel("效益值分别是:");JLabel nLabel = new JLabel("个数分别是:");JLabel tLabel = new JLabel("总效益是:");JTextField pt = new JTextField(8);pt.setText(ps);pt.setEditable(false);JTextField wt = new JTextField(8);wt.setEditable(false);wt.setText(ws);JTextField nt = new JTextField(8);nt.setEditable(false);nt.setText(ns);JTextField tt = new JTextField(8);tt.setEditable(false);tt.setText(Float.toString(totalx));p1.add(pLabel);p1.add(pt);p1.add(wLabel);p1.add(wt);p1.add(nLabel);p1.add(nt);p1.add(tLabel);p1.add(tt);c.add(p1);setVisible(true);}}四、实验结果。