贪心法 背包问题求解
2013-08-16 21:07 youxin 阅读(1462) 评论(0) 编辑 收藏 举报我们有n种物品,物品j的重量为wj,价格为pj。我们假定所有物品的重量和价格都是非负的。背包所能承受的最大重量为W。
如果限定每种物品只能选择0个或1个,则问题称为0-1背包问题。可以用公式表示为:
- 最大化
- 受限于
如果限定物品j最多只能选择bj个,则问题称为有界背包问题。可以用公式表示为:
- 最大化
- 受限于
如果不限定每种物品的数量,则问题称为无界背包问题。
各类复杂的背包问题总可以变换为简单的0-1背包问题进行求解。
现在我们可以分为2类:即物体可以分割的背包问题及物体不可分割的背包问题,把后者成为0/1背包问题。
注:贪心法只能求解可分割的背包问题,如果不分割,求的不一定是最优解。
代码如下:
/*********贪婪法求解可分割的背包问题**************/ #include<iostream> using namespace std; typedef struct{ float p; float w; float v; }OBJECT; OBJECT object[7]; float x[7]; /*输入:背包载重量M,存放n个物体的价值p,重量w信息的数组object[] 输出: n个物体被装入背包的分量x[],背包物体的总价值 */ float knapsack_greedy(float M,OBJECT object[],float x[],int n) { int i; float m,p=0; for(i=0;i<n;i++) { object[i].v=object[i].p/object[i].w; x[i]=0; //解向量赋初值 } mergeSort(object,n); //按关键值v的递减顺序排序 m=M; //背包的剩余载重量 for(i=0;i<n;i++) { if(object[i].w<=m) { x[i]=1; m-=object[i].w; p+=object[i].p; } else { x[i]=m/object[i].w; p+=object[i].p*x[i]; break; } } return p; } int main() { cout<<"请依次输入第i个物体的price 和weight"<<endl; float a,b; for(int i=0;i<7;i++) { cin>>a>>b; object[i].p=a; object[i].w=b; } cout<<endl<<"请输入最大载重量M"; float M; float resultPrice=knapsack_greedy(M,object,x,7); cout<<"最大的价值为 "<<resultPrice<<endl; }
mergeSort函数如下:

#include<iostream> using namespace std; #define INFINITE 10000 #define ARRAYSIZE 80 void merge(int a[],int p,int q,int r); void mergeSort(int a[],int p,int r) { int q; if(p<r) { q=(p+r)/2; mergeSort(a,p,q); mergeSort(a,q+1,r); merge(a,p,q,r); } } void merge(int a[],int p,int q,int r) { int i,j; int n1=q-p+1; int n2=r-q; //creat array L[1,..n1+1], R[1,..n2+1]; int *L=(int *)malloc(sizeof(int)*ARRAYSIZE); int *R=(int *)malloc(sizeof(int)*ARRAYSIZE); for(i=1;i<=n1;i++) L[i]=a[p+i-1]; for(j=1;j<=n2;j++) R[j]=a[q+j]; //哨兵牌 L[n1+1]=INFINITE; R[n2+1]=INFINITE; i=1; j=1; for(int k=p;k<=r;k++) { if(L[i]<=R[j]) { a[k]=L[i]; i=i+1; } else { a[k]=R[j]; j=j+1; } } } void main() { int n,i; cout<<"请输入数组的大小n"; cin>>n; int *a=(int *)malloc(sizeof(int)*n); cout<<"请依次输入元素的值"<<endl; int x; for(i=0;i<n;i++) { cin>>x; a[i]=x; } mergeSort(a,0,n-1); cout<<"合并排序后为"<<endl; for(i=0;i<n;i++) cout<<a[i]<<ends; cout<<endl; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
2012-08-16 php开发简单网站模板