2019.3.13贪心算法

  • 贪心算法

依据某种贪心标准,从问题的初始状态出发,直接去求每一步的最优解,通过若干次的贪心选择,最终得出整个问题的最优解。

贪心算法不是从整体上考虑问题,它所做出的选择只是在某种意义上的局部最优解

如果一个问题可以同时用几种方法解决,贪心算法应该是最好的选择之一。

所需条件:

  1. 可行的:必须满足问题​​​​​​​的约束。
  2. 局部最优:它是当前步骤中所有可行选择中最佳的局部选择。
  3. 不可更改:一旦作出选择,在算法的后面步骤就不可改变。

注意:

贪心算法不是对所有问题都能得到整体最优解,选择的贪心策略必须具备无后效性,即某个状态以后的过程不会影响以前的状态,只是当前状态有关。

求解过程:

(1)候选集合A:为了构造问题的解决方案,有一个候选集合A作为问题的可能解,即问题的最终解均取自于候选集合A。

(2)解集合S:随着贪心选择的进行,解集合S不断扩展,直到构成满足问题的完整解。

(3)解决函数solution:检查解集合S是否构成问题的完整解。

(4)选择函数select:即贪心策略,这是贪心法的关键,它指出哪个候选对象最有希望构成问题的解,选择函数通常和目标函数有关。

(5)可行函数feasible:检查解集合中加入一个候选对象是否可行,即解集合扩展后是否满足约束条件。

//A是问题的输入集合即候选集合
Greedy(A)
{
  S={ };           //初始解集合为空集
  while (not solution(S))  //集合S没有构成问题的一个解
  {
    x = select(A);     //在候选集合A中做贪心选择
    if feasible(S, x)    //判断集合S中加入x后的解是否可行
      S = S+{x};
      A = A-{x};
  }
  return S;
}

经典例题:背包问题

给定一个载重量为M的背包,考虑n个物品,其中第i个物品的重量 ,价值wi (1≤i≤n),要求把物品装满背包,且使背包内的物品价值最大。

#有两类背包问题(根据物品是否可以分割),如果物品不可以分割,称为0—1背包问题(动态规划);如果物品可以分割,则称为背包问题(贪心算法)。

有3种方法来选取物品:

(1)当作0—1背包问题,用动态规划算法,获得最优值220;

(2)当作0—1背包问题,用贪心算法,按性价比从高到底顺序选取物品,获得最优值160。由于物品不可分割,剩下的空间白白浪费。

(3)当作背包问题,用贪心算法,按性价比从高到底的顺序选取物品,获得最优值240。由于物品可以分割,剩下的空间装入物品3的一部分,而获得了更好的性能。


​​​​​​​

struct bag{
	int w;			//物品的重量
	int v;			//物品的价值
	double c;		//性价比
}a[1001];			//存放物品的数组
排序因子(按性价比降序):
bool cmp(bag a, bag b){
	return a.c >= b.c;
}
使用标准模板库函数排序(最好使用stable_sort()函数,在性价比相同时保持输入的顺序):
sort(a, a+n, cmp);
//形参n是物品的数量,c是背包的容量M,数组a是按物品的性价比降序排序
double knapsack(int n, bag a[], double c)
{
  double cleft = c;        //背包的剩余容量
  int i = 0;
  double b = 0;          //获得的价值
  //当背包还能完全装入物品i
  while(i<n && a[i].w<cleft)
  {
    cleft -= a[i].w;
    b += a[i].v;
    i++;
  }
  //装满背包的剩余空间
  if (i<n) b += 1.0*a[i].v*cleft/a[i].w;
  return b;
}
  • 个人总结:

最近感觉STL对我来说学起来真的是比较吃力,做题时发现不知道怎么运用所学的知识,还有就是即使知道了解题的思路,也没办法完整的写出程序,再就是费了九牛二虎之力写出程序,提交时出来的结果却是W或者超时...再就是可能因为刚开学的原因,时间调整的不是很好,总感觉没有足够的时间来做练习....

从原来那个狭小的空间走出来之后,才发现外面的天空有多么的广阔。天外有天,人外有人,像我这样原来一点没接触过程序的人,感到了深深的压力,这也意味着我要付出更多的努力,加油吧!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值