西海数据丨推荐 让一切变得经济实惠,贪心算法浅析

Posted NoSQLt

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了西海数据丨推荐 让一切变得经济实惠,贪心算法浅析相关的知识,希望对你有一定的参考价值。

每天一点小知识:NoSQLt提供了OPC、ModBus等适用于工业现场的工业协议接口。

贪心算法的本质:每一步到目前为止的最好的方案

优点:选择对象是单一的。

贪心算法的基本框架:可选对象的全集 S; 经每步已选对象的集合T;

可想而知,T是S的一个子集。

判断解合法的函数 isvalid(T); 评价解的函数 payoff(T);

从S中挑选出子集T,使T合法 即 isvalid(T)==true,并且使payoff(T)的值最大

算法:从空集开始,每次加一个元素,使得payoff的值尽可能的大。

读到这,我们会觉得贪心算法智商大过10的人都能想到,这一点是谁都承认的,但是贪心算法真正的难点是证明贪心选择的性质。小编在这里用正常的人话解释一下这句话就是说 如何证明这个子集就是最优解。这或许就会难到一部分人,那就随我继续往下看。

首先比较动态规划和贪心算法:

动态规划: choice(X)= max{ choice(Y)+ payoff (y,x)}

状态x下最优解 状态y下最优解 状态转换时的收益

动态规划中 X是固定的,Y取决于X

贪心算法: choice(X)= choice(Y) + max{payoff (y,x)}

贪心算法中,Y是固定的,选收益最大的,再变到X状态。X取决于Y。

举个俗套的例子 换零钱问题 用 1,2,5 分钱 凑出 n 这个面值,且使用的硬币要最少。

贪心算法的本质就是追求利益的最大化,怎么用硬币最少?那就尽可能多使用5 分硬币,之后尽可能多的用2分,最后才是1分补齐。

现在是重点啦,如何证明我的贪心算法是对的

若n=5k,则所有自然数可以用 5k+1,5k+2,5k+3,5k+4来表示。

k=0时,n=0,1,2,3,4用枚举法便可证明贪心选择是对的;

若k=m时成立,那么k=m+1时是否成立

n=5(m+1),他之前用硬币补足的面额可能是 5(m+1)-1; 5(m+1)-2和 5(m+1)-5.

之前为 5(m+1)-1时,m个5分,两个2分,再加上现在的1分才是5(m+1);

之前为 5(m+1)-2时,m个5分,一个2分,一个1分,再加上现在的2分才是5(m+1);

之前为 5(m+1)-5时,m个5分,再加上现在的5分 ,才是5(m+1);

上述三种可视为动态规划的三种情况,分别用了m+3,m+3和m+1个硬币。也证明了贪心算法的成立。

但不是所有都能用贪心算法,若面值为1,2,5,7 。并要求凑出10时,只顾追求用最多的7反倒不是最好的选择。

之前讲过的背包问题用贪心算法也可以巧妙解决,在此附上贪心算法的代码(以零钱问题为例)

const unsigned int N = 7; //钱币的种类数

const unsigned int a[N] = {1,2,5,10,20,50,100} ; //钱币的面额

const unsigned int J = n; //要找的零钱数(实际问题中n是输入的实数)

int i=N-1,j=J,r[N]={0};

while(j>0)

{

r[i]=j/a[i];

j-=r[i]*a[i];

i--;

}

for(size_t i=0;i<N;i++)

{

cout<<r[i]<<" ";

greedy_sum += r[i];

}




以上是关于西海数据丨推荐 让一切变得经济实惠,贪心算法浅析的主要内容,如果未能解决你的问题,请参考以下文章

西海数据丨推荐 数据结构与算法 通俗易懂讲解 快速排序

西海数据丨推荐 有史以来最晦涩的算法——Paxos算法!

西海数据丨推荐 非对称加密算法DH,RSA

西海数据丨推荐 常用数据挖掘算法从入门到精通 第十一章 支持向量机算法

西海数据丨推荐 初识支持向量机

西海数据丨推荐 TCP协议相关解释