在前面我们已经有分享过递归和回溯算法的思想,再结合最近在学图的应用时,遇到最小生成树和最短路径等问题时,都提到一个贪心的思想。今天,我们就来总的看一下这个贪心算法的内容吧
1.贪心算法(有时也叫贪婪算法)是指在对问题进行求解时,在每一步选择中都采取最好或者最优(即最有利)的选择
,从而希望能够导致结果是最好或者最优的算法。贪心算法所得到的结果不一定是最优的结果(有时候会是最优解),但是都是相对近似(接近)最优解的结果
2.贪心算法一般按如下步骤进行:
①建立数学模型来描述问题 。
②把求解的问题分成若干个子问题 。
③对每个子问题求解,得到子问题的局部最优解 。
④把子问题的解局部最优解合成原来解问题的一个解 。
3.贪心算法是一种对某些求最优解问题的更简单、更迅速的设计技术。贪心算法的特点是一步一步地进行,常以当前情况为基础根据某个优化测度作最优选择,而不考虑各种可能的整体情况,省去了为找最优解要穷尽所有可能而必须耗费的大量时间。贪心算法采用自顶向下,以迭代的方法做出相继的贪心选择,每做一次贪心选择,就将所求问题简化为一个规模更小的子问题,通过每一步贪心选择,可得到问题的一个最优解。虽然每一步上都要保证能获得局部最优解,但由此产生的全局解有时不一定是最优的,所以贪心算法不要回溯 。
4.贪心算法也存在如下问题:
①不能保证解是最佳的。因为贪心算法总是从局部出发,并没从整体考虑 ;
②贪心算法一般用来解决求最大或最小解 ;
③贪心算法只能确定某些问题的可行性范围 。
5.下面我们就来说一个经典问题——背包问题来体会一下贪心算法吧
题目:有一个背包,背包容量是M=150。有7个物品,物品可以分割成任意大小。要求尽可能让装入背包中的物品总价值最大,但不能超过总容量。
用贪心算法解背包问题的基本步骤:首先计算每种物品单位重量的价值v[i]/w[i],然后,依贪心选择策略,将尽可能多的单位重量价值最高的物品装入背包。若将这种物品全部装入背包后,背包内的物品总重量未超过C,则选择单位重量价值次高的物品并尽可能多地装入背包。依此策略一直地进行下去,直到背包装满为止。
代码实现:
#include <iostream>
using namespace std;
//按照单位重量的价值量大小降序排列
void Sort(int n, float* w, float* v)//最后得到从大到小的单位重量价格量
{
int i, j;
float temp1, temp2;
for (i = 1; i <= n; i++)
for (j = 1; j <= n - i; j++)//冒泡排序
{
temp1 = v[j] / w[j];
temp2 = v[j + 1] / w[j + 1];
if (temp1 < temp2)
{
swap(w[j], w[j + 1]);
swap(v[j], v[j + 1]);
}
}
}
int main()
{
float w[101];//用来表示每个物品的重量
float v[101];//用来表示每个物品的价值量
float x[101];//表示最后放入背包的比例
int n;//物品数
float M;//背包最大容纳重量
cout << "请输入物品数" << endl;
cin >> n;
cout << "请输入背包最大容量" << endl;
cin >> M;
//依次输入每件物品的重量和价值量
cout << "依次输入每件物品的重量和价格量" << endl;
for (int i = 1; i <= n; i++)
cin >> w[i] >> v[i];
//按照单位重量的价值量大小降序排列
Sort(n, w, v);
int i;
for (i = 1; i <= n; i++)
x[i] = 0;//初始值,未装入背包,x[i]=0
float c = M;//更新背包容纳量
for (i = 1; i <= n; i++)
{
if (c < w[i]) break;//不能完全装下
x[i] = 1;
c = c - w[i];
}
if (i <= n)
x[i] = c / w[i];
//输出
for (int i = 1; i <= n; i++)
cout << "重量为" << w[i] << "价值量为" << v[i] << "的物品" << "放入的比例为" << x[i] << endl;
return 0;
}
程序执行图:
好啦,关于这个贪心算法下的背包问题就分享到这啦,后面还有一种叫0-1背包的问题,这是贪心算法解决不了的,需要用到动态规划等内容。
本贴为博主亲手整理。如有错误,请评论区指出,一起进步。谢谢大家的浏览.