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