关于贪婪算法的一点认识

贪婪算法是求问题的最优解,最典型的是0/1背包问题,如下:

有n个物品和一个容量为c的背包,从n个物品中选取装包的物品,物品i的重量是wi,价值是pi,一个可行的背包装载是指:装包的物品重量不超过物品的容量。一个最佳的背包装载是指物品总价值最高的可行的背包装载。仔细想想这东西其实很难求最优解的,不过我们可以先从简单的入手:“找零钱”,用100元买了不足100元的商品,对方怎么找零最少呢?这个问题小学生到知道,代码如下:

function givechange(number){
if(number<1) return;
let giveAry = [100,50,20,10,5,1];
for(let i=0;i<giveAry.length;i++){
if(number<1) return;
if(number < giveAry[i]) continue;
console.log(`需要${Math.floor(number/giveAry[i])}张${giveAry[i]}元`);
number = number%giveAry[i];
}
}

givechange(1236);

实质是这样的:好比找给你的钱要一张一张的找,每次找给你的钱都是能给你的最大面额,这就是他的贪婪算法。

另一个是装箱问题:一个大船要装货物,所有货箱的大小都一样重量却不同,第i个货箱的重量为wi货船最大载重量为C,货船上最多能装多少货物?(不考虑货船能装多少货箱)这都是最优解问题。

function boxing(boxary,threshold){
boxary.sort(function(a,b){return b-a});
let val = 0,i=0;
for(i;i<boxary.length;i++){
val += boxary[i];
if(val >= threshold) {
val -= boxary[i];
break;
};
}
console.log(`装了${i}箱,总重量${val}`);
}

 boxing([2,3,5,7,34,56,78,1,5,67],200);

上面两个是小甜点,你很快会发现这样有问题,每次都装最终的当装不下的时候应该让最小的去试试。

以上都是0/1背包问题的具体实例,广泛来讲,背包问题贪婪准则有三种:

1,从剩余物品中选出能装入背包价值最大的物品。

假如说 ,n=3,w=[100,10,10],p=[20,15,15],c=105.使用这个准则得到的解是[1,0,0],可是最优解是[0,1,1];

2,从剩余物品选出能装入背包重量最小的物品。

例如:n=2,w=[10,20],p=[5,100],c=25,使用这个准则得到的解是[1,0],其实最优解是[0,1];

3,从剩余物品中选出可以装包的pi/wi最大的物品,

例如,n=3,w=[20,15,15],p=[40,25,25],c=30,依然不能得到最优解。

你可能听过任务调度问题,例如cpu任务调度的算法,这种都是典型的NP复杂问题,是不能在多项式时间内解决的。

难道就束手无策了吗?用贪婪算法我们可以求出解,但不一定是最优解,可是大部分情况下都是或者都接*最优解,这就可以了。

也许你会问前端学这有啥用呢?

举个例子:前端有个查看图片的瀑布流插件,下拉会更新图片,图片的宽高比是不确定,怎么样排列以后瀑布流底部最接*与*整呢?这不就是一个简单的0/1背包问题吗?

 

posted @ 2018-12-25 16:56  node-吉利  阅读(215)  评论(0编辑  收藏  举报