贪心算法:
本周的练习主要针对贪心算法,又名贪婪法,是寻找最优解问题的常用方法,这种方法模式一般将求解过程分成若干个步骤,但每个步骤都应用贪心原则,选取当前状态下最好/最优的选择(局部最有利的选择),并以此希望最后堆叠出的结果也是最好/最优的解。
贪心算法的一般流程:
Greedy(C) //C是问题的输入集合即候选集合
{
S={ }; //初始解集合为空集
while (not solution(S)) //集合S没有构成问题的一个解
{
x=select(C); //在候选集合C中做贪心选择
if feasible(S, x) //判断集合S中加入x后的解是否可行
S=S+{x};
C=C-{x};
}
return S;
实例分析:背包问题
问题描述 有一个背包,背包容量是M=150。有7个物品,物品可以分割成任意大小。要求尽可能让装入背包中的物品总价值最大,但不能超过总容量。
物品 A B C D E F G
重量 35 30 60 50 40 10 25
价值 10 40 30 50 35 40 30
分析如下
目标函数: ∑pi最大
约束条件是装入的物品总重量不超过背包容量:∑wi<=M( M=150)。
贪心策略:
- 选择价值最大的物品
- 选择价值最大的物品
- 选择单位重量价值最大的物品
算法设计:
- 计算出每个物品单位重量的价值
- 按单位价值从大到小将物品排序
- 根据背包当前所剩容量选取物品
- 如果背包的容量大于当前物品的重量,那么就将当前物品装进去。否则,那么就将当前物品舍去,然后跳出循环结束。
用代码实现:
#include <iostream>
#include <algorithm>
using namespace std;
typedef struct
{
int w;
int v;
double avg;
}P;
bool cmp(P a,P b)
{
return a.avg > b.avg;
}
int main()
{
P *p;
int n,i,m;//n 物品个数 m背包容量
while(cin >> n >> m)
{
p=new P[n];
for(i=0; i<n; i++)
{
cin >> p[i].w >> p[i].v;
p[i].avg = p[i].v/p[i].w*1.0;
}
sort(p,p+n,cmp);
int maxvalue = 0;
for(i=0; i<n; i++)
{
if(p[i].w <= m)
{
m -= p[i].w;
maxvalue += p[i].v;
}
else
{
break;
}
}
cout << maxvalue << endl;
}
return 0;
}