背包问题的贪心算法


1. 贪心算法的基本原理:

贪心算法总是作出在当前看来最好的选择。也就是说贪心算法并不从整体最优考虑,它所作出的选择只是在某种意义上的局部最优选择。当然,希望贪心算法得到的最终结果也是整体最优的。虽然贪心算法不能对所有问题都得到整体最优解,但对许多问题它能产生整体最优解。如单源最短路经问题,最小生成树问题等。在一些情况下,即使贪心算法不能得到整体最优解,其最终结果却是最优解的很好近似。?

贪心算法求解的问题一般具有两个重要性质:贪心选择性质和最优子结构性质。

(1)所谓贪心选择性质是指所求问题的整体最优解可以通过一系列局部最优解的选择,即贪心选择来达到。这是贪心算法可行的第一个基本要素,也是贪心算法与动态规划算法的主要区别。

(2)当一个问题的最优解包含其子问题的最优解时,称此问题具有最优子结构性质。问题的最优子结构性质是该问题可用动态规划算法或贪心算法求解的关键特征。

(2)背包问题的贪心算法实现

算法实现主要代码如下:

#include <iostream.h>

#include <string>

#include <conio.h>

using namespace std;

?

//物品信息结构体

struct goodinfo

{

????float p; //物品效益

????float w; //物品重量

????float X; //物品该放的数量

????int flag; //物品编号

};

?

//*********按物品效益,重量比值做升序排列***************//

void Insertionsort(goodinfo goods[],int n)

{

????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];

????}

????cout<<"最优解为:"<<endl;

????for(i=1;i<=n;i++)

????{

????????cout<<"第"<<i<<"件物品要放:";

????????cout<<goods[i].X<<endl;

????}

}

?

//*************主函数***************//

void main()

{

????int n;

char j;

????float M;

????goodinfo *goods;//定义一个指针

????cout<<"#####背包问题的贪心算法#####\n"<<endl;

?

????while(!(j==‘n‘||j==‘N‘))

????{

????????cout<<"物品的种类数量:";

????????cin>>n;

????????goods=new struct goodinfo [n+1];//

????????cout<<"背包的最大容量:";

????????cin>>M;

????????cout<<endl;

????????int i;

????????for(i=1;i<=n;i++)

????????{

????????????goods[i].flag=i;

????????????cout<<"第"<<i<<"件物品:"<<endl;

????????????cout<<"重量:";

????????????cin>>goods[i].w;

????????????cout<<"价值:";

????????????cin>>goods[i].p;

????????????goods[i].p=goods[i].p/goods[i].w;//得出物品的重量比

????????????cout<<endl;

????????}

????????Insertionsort(goods,n);

????????bag(goods,M,n);

????????

????????cout<<endl<<"是否继续(y/n)?"<<endl;

????????j= getch();

????????cout<<"---------------------"<<endl;

????}

}

编译并运行程序。

(3)算法的时间复杂性和空间复杂性

以上算法的时间复杂度和空间复杂度为O(n2),其中时间复杂度基本已经不能再优化了,但空间复杂度可以优化到O(n)。


程序运行结果如下:

注意背包问题与0-1背包问题的不同,虽然这两个问题极为相似,但背包问题可以用贪心算法求解,而对于0-1背包问题,贪心选择算法不能得到最优解。因为在0-1背包问题的这种情况下,它无法保证最后能将背包装满,部分闲置的背包空间,使每公斤背包的价值降低了。动态规划算法可以有效的解0-1背包问题。

时间: 2024-08-03 01:10:22

背包问题的贪心算法的相关文章

背包问题:0/1背包问题 普通背包问题(贪心算法只适用于普通背包问题)

//sj和vj分别为第j项物品的体积和价值,W是总体积限制. //V[i,j]表示从前i项{u1,u2,…,un}中取出来的装入体积为j的背包的物品的最大价值. 第一种:0/1背包问题 最大化 ,受限于  1)若i=0或j=0,  V[i,j] = 0 2)若j<si, V[i,j] = V[i-1,j] 3)若i>0且j>=si, V[i,j] = Max{V[i-1,j],V[i-1,j-si]+vi} 第二种:背包问题:在选择物品i装入背包时,可以选择物品i的一部分,而不一定要全部

部分背包问题的贪心算法正确性证明

一,部分背包问题介绍 首先介绍下0-1背包问题.假设一共有N件物品,第 i 件物品的价值为 Vi ,重量为Wi,一个小偷有一个最多只能装下重量为W的背包,他希望带走的物品越有价值越好,请问:他应该选择哪些物品? 0-1背包问题的特点是:对于某件(更适合的说法是:某类)物品,要么被带走(选择了它),要么不被带走(没有选择它),不存在只带走一部分的情况. 而部分背包问题则是:可以带走一部分.即,部分背包问题可带走的物品 是可以 无限细分的.(连续与离散的区别) 可以把0-1背包问题中的物品想象的一个

数据结构与算法学习之路:背包问题的贪心算法和动态规划算法

一.背包问题描述: 有N种物品和一个重量为M的背包,第i种物品的重量是w[i],价值是p[i].求解将哪些物品装入背包可使这些物品的费用总和不超过背包重量,且价值总和最大. 二.解决方法: 1.贪心算法:贪心算法基于的思想是每一次选择都作当前最好的选择,这样最后的结果虽然不一定是最优解,但是也不会比最优解差很多. 举个例子说明可能好懂一些:一帮基友去聚餐,菜是一份一份上的,我每一次夹菜都只夹牛肉/海鲜吃,可能到最后我吃的牛肉/海鲜很多,但不一定代表我吃掉的东西的总价值最高,但是相对来说价值也很高

背包问题(贪心算法)

贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择.也就是说,不从整体最优上加以考虑,他所做出的是在某种意义上的局部最优解. 贪心算法还是比较好理解的一个算法,以前我也是这样认为的,感觉贪心就是每一步都做到最优解就可以了,但是后来结合问题发现自己的理解存在着一些问题.贪心算法比较经典的题目之一就是单源最短路径问题,这个问题在一些步骤上面我想了很久,有些细节想不通.这个问题以后有机会再讲.本次讲一讲背包问题. 背包问题就是有若干物品,每个物品有自己的价值和重量.背包有总重

数据结构之贪心算法(背包问题的思考)-(十)

贪心策略.关于贪心算法的思考,思考过程都放在代码中了. package com.lip.datastructure; /** *贪心算法:装箱问题的思考 * @author Lip *装箱问题可以是时间调问题的延伸,当一个箱子没有容积限制,那么就是时间调度问题 *在时间调度问题中:存在两个可以讨论的问题.1.平均最短时间 2.总的最短时间 *这两个问题都和装箱问题中问题如此类似. */ /* * 上面是我理解的装箱问题,本来是想说背包问题的 * 背包问题的描述:有N件物品和一个容量为V的背包.第

[C++] 贪心算法之活动安排、背包问题

一.贪心算法的基本思想 在求解过程中,依据某种贪心标准,从问题的初始状态出发,直接去求每一步的最优解,通过若干次的贪心选择,最终得出整个问题的最优解. 从贪心算法的定义可以看出,贪心算法不是从整体上考虑问题,它所做出的选择只是在某种意义上的局部最优解,而由问题自身的特性决定了该题运用贪心算法可以得到最优解.如果一个问题可以同时用几种方法解决,贪心算法应该是最好的选择之一. 二.贪心算法的基本要素 (1)最优子结构性质 (2)贪心选择性质(局部最优选择) 三.贪心算法实例 1.活动安排 设有n个活

某种 找换硬币问题的贪心算法的正确性证明

一,问题介绍 最近一直在看贪心算法的正确性证明(如何证明贪心算法获得的解一定是最优解),感觉“剪枝”技巧用得比较多.再看了下<算法导论>中贪心算法一章里面的一个练习---找换硬币问题.这个问题对于某些 面值的硬币 是有最优解的,故记录下其中的一些证明思路. 考虑用最少的硬币数 来找 n 分钱的问题,假设每个硬币的值都是整数. 如果可换的硬币的单位是 c 的幂,也就是 c0,c1,... ,ck ,其中整数 c>1,k>=1 证明贪心算法总可以产生一个最优解. 二,找换硬币的贪心策略

算法导论笔记——第十六章 贪心算法

通常用于最优化问题,我们做出一组选择来达到最优解.每步都追求局部最优.对很多问题都能求得最优解,而且速度比动态规划方法快得多. 16.1 活动选择问题 按结束时间排序,然后选择兼容活动. 定理16.1 考虑任意非空子问题Sk,令am是Sk中结束时间最早的活动,则am在Sk的某个最大兼容活动子集中. 16.2 贪心算法原理 设计贪心算法步骤: 1>将最优化问题转化为这样的形式:对其做出一次选择后,只剩下一个子问题需要求解. 2>证明作出贪心选择后,原问题总是存在最优解,即贪心选择总是安全的. 3

贪心算法总结

贪心算法总结 一.算法思想 贪心法的基本思路: 从问题的某一个初始解出发逐步逼近给定的目标,以尽可能快的地求得更好的解.当达到某算法中的某一步不能再继续前进时,算法停止. 该算法存在问题: 1. 不能保证求得的最后解是最佳的. 2. 不能用来求最大或最小解问题: 3. 仅仅能求满足某些约束条件的可行解的范围. 实现该算法的过程: 从问题的某一初始解出发: while 能朝给定总目标前进一步: 求出可行解的一个解元素: 由所有解元素组合成问题的一个可行解: 二.ACM做题情况 本专题,学习贪心算法