【算法基础】----贪心算法
来源:互联网 发布:mac如何删除用户 编辑:程序博客网 时间:2024/04/29 07:36
贪心算法是常见的基础算法,它在求解问题时总想用当前看来最好的方法去实现,而到了下一步,再用下一步时最好的方法来解决,因此有了贪心的名字。此方法不从整体去考虑,仅是在某种意义上的局部最优求解。虽然贪心算法不是对所有的问题都能得到整体最优解,但是面对范围相当广泛的很多问题时,能产生整体最优解或是整体最优解的高度近似解,因此可见贪心算法只是追去一定范围内的最优。
1. 贪心算法的基础
贪心算法在解决一个问题时,通常会从某一个初始解出发,逐步逼近给定的目标,以便尽快求出更好的解。
当达到算法中的某一步不能在继续进行下去的时候,就停止算法,给出一个近似解。由贪心算法的特点和思路可以看出,贪心算法存在以下3个问题。
(1).不保证最后得解是最优的(实际上它从不考虑最后得结果)
(2).不能用来求最大或最小解的问题
(3).只能满足某些约束条件的可行解的范围
而通常情况下,贪心算法的思路如下:
(1).建立数学模型来描述问题
(2).将求解的问题分解为若干范围较小的子问题
(3).对每一子问题求解,得到子问题的局部最优解
(4).把子问题的局部最优合并成原问题的局部最优解
下面我们通过两个例子来描述贪心算法
1. 找零方案
在现实生活中,我们买东西经常需要找零,而商店找零的方法通常是优先找面额大的,再找小面额的。因为我们永远都不是商店的最后一个顾客,因此商店为了保证下一个顾客依然有零钱可以找,会尽可能的把面额大的找给我们,而把零钱留给自己。
人民币有100、50、20、10、5、1、0.5、0.2、0.1(单位:元)等多种面额,设计一个找零算法,使得面值大的尽可能多的被找。
#include <iostream>using namespace std ;int main(void) { int i ; float money ; float x[9] = {100 , 50 , 20 , 10 , 5 , 1 , 0.5 , 0.2 , 0.1} ; cin >> money ; for(i = 0 ; i < 9 ; ++ i) { while(money >= x[i]) { money -= x[i] ; cout << x[i] << " " ; } } return 0 ;}
上面只是一个简单的例子,下面我们来详细的讨论一下装箱问题
假设有编号为0,1,2.....n-1的n中物品,体积分别为v0,v1,v2......v(n-1),现需要将这些物品装进容积为V的若干箱子中,且箱子的体积不会小于任一物品。不同的装法可能。需要数量不同的箱子,现在我们需要用尽可能少的箱子装下所有的物品。
例:箱子的容量为10,有四个物品,体积分别为6,7,4,3,如果按照6->7->4->3的顺序,需要3个箱子,而如果按照6->4->7->3的顺序,只需要两个箱子。
选择数据结构
数据结构的选择关系到算法的高效与否。
存储链式结构,不涉及元素的进出,排除了栈和队列。有数组和链表可供选择,而我们在装箱问题中选择链表的原因有一下两点:
1.建立数据结构时,我们事先并不知道需要多少箱子,即无法确定元素的个数。
2.在算法的运行中,我们一旦确定了物品装进哪个箱子,就需要将物品和箱子建立某中内存上的联系,使得通过箱子可以找到其中的物品。
而数组显然不具备以上功能,因此我们选择链表。
typedef struct gNode { //structs array int num ; int gV ;}gNode ;typedef struct ElemNode { //物品节点 int gV ; int gNum ; struct ElemNode * next ; //节点中指向下一个物品的指针}ElemNode ;typedef struct gBox { //箱子节点 int V ; //箱子的容积 ElemNode * nextNode ; //箱子节点中指向其中物品的指针 struct gBox * nextBox ; //箱子节点中指向下一个箱子的节点}gBox ;
最终程序运行时的数据结构应该是这样
实际代码如下:
#include <stdio.h>#include <stdlib.h>const int maxV = 10 ;typedef struct gNode { //structs array int num ; int gV ;}gNode ;typedef struct ElemNode { //物品节点 int gV ; int gNum ; struct ElemNode * next ; //节点中指向下一个物品的指针}ElemNode ;typedef struct gBox { //箱子节点 int V ; //箱子的容积 ElemNode * nextNode ; //箱子节点中指向其中物品的指针 struct gBox * nextBox ; //箱子节点中指向下一个箱子的节点}gBox ;gBox * Pack(gBox * hB , gNode * hG , int num) { int i ; gBox * t , * iBox , * newBox; ElemNode * newNode = NULL , * findEnd = NULL ; hB = t = (gBox *)malloc(sizeof(gBox)) ; //拿出第一个物品,必定打开一个箱子 t -> V = maxV ; // t -> nextNode = NULL ; //初始化箱子 t -> nextBox = NULL ; // for(i = 0 ; i < num ; ++ i) { newNode = (ElemNode *)malloc(sizeof(ElemNode)) ; //每一个物品,都需要分配一块内存 newNode ->gV = (hG+i)->gV ; newNode ->gNum = (hG+i)->num ; newNode ->next = NULL ;//从第一个物品开始装,等到所有的物品都遍历完,说明装箱结束。 for(iBox = hB ; iBox ; iBox = iBox ->nextBox) { //每拿到一个物品,都要从第一个箱子开始遍历,直到找到一个箱子或者现有的箱子都没法装下 if((hG + i) -> gV < iBox ->V) { //如果当前箱子的剩余容积大于物品的体积,可以放 findEnd = iBox ->nextNode ; //使用findEnd指针来找到物品链的末尾 while(findEnd ->next || findEnd) { //使用或运算符可以兼容箱子中有物品或没物品 findEnd = findEnd -> next ; //两种情况 } findEnd ->next = newNode ; iBox ->V -= newNode ->gV ; } } newBox = (gBox *)malloc(sizeof(gBox)) ; //如果当前所有箱子都不符合条件,创建一个新的箱子节点 newBox ->V = maxV ; //并初始化 newBox ->nextNode = NULL ; newBox ->nextBox = NULL ; t = t ->nextBox = newBox ; //然后将新的箱子挂在箱子链的末尾 t ->nextNode = newNode ; //最后将新的物品挂在新的箱子上 }}void Display(gBox * hBox) { int i = 1 ; ElemNode * travelNode = NULL ; gBox * travelBox = NULL ; for(travelBox = hBox ; travelBox ; travelBox = travelBox ->nextBox) { printf("第%d个箱子中装有物品:" , i ++) ; travelNode = travelBox ->nextNode ; while(travelNode) { printf("%4d" , travelNode ->gNum) ; } printf("\n") ; }}int main(void) { int num , i ; printf("please input the number of boxes:") ; scanf("%d" , num) ; gNode * hG = (gNode *)malloc(num * sizeof(gNode)) ; //创建结构体数组,用来存储物品信息 for(i = 0 ; i < num ; ++ i) { (hG+i)->num = i ; printf("Input No.%d node:" , i) ; scanf("%d" , &(hG+i)->gV ) ; } gBox * hBox = NULL ; hBox = Pack(hBox , hG , num) ; Display(hBox) ; return 0 ;}
- 【算法基础】----贪心算法
- 算法基础(5) 贪心算法
- 基础算法之贪心算法
- 贪心算法--1基础
- 贪心算法基础
- 【贪心算法(一)】贪心算法基础
- 贪心算法基础(二)
- 基础入门之贪心算法
- 零基础学贪心算法
- 基础算法之贪心法1
- 基础练习 Huffuman树(贪心算法)
- 基础练习 Huffuman树(贪心算法)
- 拟阵基础与贪心算法
- 贪心算法 & 动态规划基础题
- 算法基础-->贪心和动态规划
- 贪心算法
- 贪心算法
- 贪心算法
- Hadoop基准测试
- 判断.java文件中getConnection与cleanUp数量是否匹配
- Android中MenuInflater实例 菜单实例
- ubuntu14.04安装chrome
- 移动开发者必须了解的三大职业趋势
- 【算法基础】----贪心算法
- IOS控件圆角、描边
- Oracle命令
- ActiveAndroid入门
- JavaScript入门篇之新生代JSON遇XML
- 详解Android Handler的使用-别说你不懂handler
- .Net互操作之PInvoke
- php之qq登陆
- 投影矩阵的推导(Deriving Projection Matrices)