贪心算法的分数背包问题的介绍与理解1(含c源代码)
来源:互联网 发布:qq三国js技能介绍 编辑:程序博客网 时间:2024/04/30 23:13
分数背包问题:
在选择物品i装入背包时,可以选择物品i的一部分,而不一定要全部装入背包,1≤i≤n。
这类问题都具有最优子结构性质,极为相似,但背包问题可以用贪心算法求解,而0-1背包问题却不能用贪心算法求解。用贪心算法解背包问题的基本步骤是,首先计算每种物品单位重量的价值Vi/Wi,然后,依贪心选择策略,将尽可能多的单位重量价值最高的物品装入背包。若将这种物品全部装入背包后,背包内的物品总重量未超过C,则选择单位重量价值次高的物品并尽可能多地装入背包。依此策略一直地进行下去,直到背包装满为止。
算法knapsack的主要计算时间在于将各种物品依其单位重量的价值从大到小排序。因此,算法的计算时间上界为O(nlogn)。为了证明算法的正确性,还必须证明背包问题具有贪心选择性质。
贪心算法的性质:
我们可以通过做出局部最优选择来构造全局最优解。贪心算法中,我们总是做出当时看来最佳的选择,然后求解剩下的唯一的子问题。贪心算法进行选择时可能依赖之前做出的选择,但不依赖任何将来的选择或是子问题的解。
贪心算法的设计步骤:
1. 将最优化问题转化为这样的形式:对其做出一次选择后,只剩下一个子问题需要求解。
2.证明做出贪心选择后,原问题总是存在最优解(贪心算法总是安全的)
3. 证明做出贪心选择后,剩余的子问题满足性质:其最优解与贪心选择组合即可得到原问题的最优解,这样就得到了最优子结构。
例子1: 输入物品数量:3 总重量 :7 求最优的方案?
编号: 1 2 3
输入的重量: 1 4 3
输入的价格对应为 : 4 8 9
例子2: 输入物品数量:3 总重量 :50 求最优的方案?
编号: 1 2 3
输入的重量: 10 20 30
输入的价格对应为 : 60 100 140
C源代码:
#include <stdio.h>struct goodinfo { float p; //物品效益 float w; //物品重量 float X; //物品该放的数量 int flag; //物品编号 };//物品信息结构体 int partion1(goodinfo *arr,int p,int r); void quicksort1(goodinfo *arr,int p,int r){if(p<r){int q;q=partion1(arr,p,r);quicksort1(arr, p, q-1);quicksort1(arr, q+1, r);} }int partion1(goodinfo *arr,int p,int r){int x,i,j;x=arr[r].p;i=p-1;for(j=p;j<r;j++){if(arr[j].p>=x)//修改大于就是从小到大序 {i=i+1;if(j!=i){goodinfo temp=arr[j];arr[j]=arr[i];arr[i]=temp; } } } goodinfo temp; temp=arr[r]; arr[r]=arr[i+1]; arr[i+1]=temp; return i+1;} //快速排序上面的是选择最后一个点为基点; void Insertionsort(goodinfo goods[],int n) //插入排序,按pi/wi价值收益进行排序 { int j,i; for(j=2;j<=n;j++) { goods[0]=goods[j]; i=j-1; while (goods[0].p>goods[i].p) { goods[i+1]=goods[i]; i--; } goods[i+1]=goods[0]; } } //按物品效益,重量比值做升序排列 void bag(goodinfo goods[],float M,int n) { float cu; int i,j; for(i=1;i<=n;i++) goods[i].X=0; cu=M; //背包剩余容量 for(i=1;i<n;i++) { if(goods[i].w>cu) //当该物品重量大与剩余容量跳出 break; goods[i].X=1; cu=cu-goods[i].w; //确定背包新的剩余容量 } if(i<=n) goods[i].X=cu/goods[i].w; //该物品所要放的量 /*按物品编号做降序排列*/ for(j=2;j<=n;j++) { goods[0]=goods[j]; i=j-1; while (goods[0].flag<goods[i].flag) { goods[i+1]=goods[i]; i--; } goods[i+1]=goods[0]; } printf("最优解为:\n");float sum=0; for(i=1;i<=n;i++) { printf("第%d件物品要放:",i); printf("重量大小%f\n",goods[i].X*goods[i].w); printf("价格%f:",goods[i].p) ; sum+=goods[i].X*goods[i].w*goods[i].p; } printf("最优解的效益%f\n",sum); } int main() { printf("|--------运用贪心法解分数背包问题---------|\n"); int j=1,n; float M; goodinfo *goods; //定义一个指针 while(j) { printf("请输入物品的总数量:"); scanf("%d",&n); goods=new struct goodinfo [n+1];// printf("请输入背包的最大容量:"); scanf("%f",&M); printf("\n"); int i; for(i=1;i<=n;i++) { goods[i].flag=i; printf("请输入第%d件物品的重量:",i); scanf("%f",&goods[i].w); printf("请输入第%d件物品的效益:",i); scanf("%f",&goods[i].p); goods[i].p=goods[i].p/goods[i].w; //得出物品的效益,重量比 printf("重量的平均价格:#%f",goods[i].p); //很清晰的能够看到运行的过程; printf("\n"); } //Insertionsort(goods,n); //插入的思想 quicksort1(goods,1,n); //快排的思想; //注意这里的数组是从1下标开始,如果写成0.就会出现溢出的现象; bag(goods,M,n); printf("press <1> to run agian\n"); printf("press <0> to exit\n"); scanf("%d",&j); } }
总结:
贪心算法解决了分数背包问题,当然解决该类问题的同时,由于价格/重量的大小从大到小排序(时间复杂度O(nlgn),用到了快排和插入两种排序方式),从而取物品也是根据这个顺序来不断的抽取物品,直到达到目标的重量;其中会出现一种当有几件物品的价格/重量的大小相同时,它只取排在前面的那样物品;从而结果会不唯一,但他的最优效益唯一;这个也不能处理0-1背包问题(取物品只有取和不取,不存在只取物品的一部分),后面将会运用动态规划的方法去解决该类问题!!
- 贪心算法的分数背包问题的介绍与理解1(含c源代码)
- 动态规划0-1背包问题的介绍与理解(含c源代码)
- 贪心算法活动选择问题介绍与理解(含c源代码)
- 线性时间的桶排序介绍与理解(含c源代码)
- 分数背包问题(贪心算法)
- 0/1背包问题的贪心算法
- 背包问题的贪心算法
- 背包问题的贪心算法
- 贪心算法之埃及分数问题(附c++源代码)
- 用贪心算法求解的0-1背包C++源代码
- 算法分析与设计-15-背包问题的贪心算法
- 浅谈动规贪心 与0-1背包和分数背包问题
- 用贪心算法实现的背包问题
- 背包问题的贪心算法求解
- 基于贪心算法的背包问题
- 一般背包问题的贪心算法
- 基于贪心算法的0/1背包问题
- 用贪心算法实现的背包问题(java语言)
- Java类加载器总结
- 使用Jlink对FL2440开发板进行烧录
- 隐马尔科夫模型
- 利用注解加拦截器实现struts2的权限设置
- iOS设计模式 - (3)简单工厂模式
- 贪心算法的分数背包问题的介绍与理解1(含c源代码)
- 树状数组——————二分索引树
- hdu 1028 Ignatius and the Princess III
- 高效求解平方根的倒数的函数实现
- 如何用Cocos2d-x创建lua项目以及lua项目如何调用cpp文件(图文讲解)
- Android Fragment IllegalStateException: Fragment not attached to Activity
- SpringMVC表单标签简介
- Three.js - 用100行javascript代码创建一座城市
- POJ 1979 Red and Black