【贪心算法】

贪心(Greedy)

  • 贪心策略,也称为贪婪策略
  • 定义:每一步都采取当前状态下最优的选择(局部最优解),从而希望推导出全局最优解
  • 贪心的应用
    哈夫曼树
    最小生成树算法:Prim、Kruskal
    最短路径算法:Dijkstra

问题1:最优装载

在这里插入图片描述
贪心策略:每一次都优先选择重量最小的古董

① 选择重量为 2 的古董,剩重量 28
② 选择重量为 3 的古董,剩重量 25
③ 选择重量为 4 的古董,剩重量 21
④ 选择重量为 5 的古董,剩重量 16
⑤ 选择重量为 7 的古董,剩重量 9
根据上面的选择,最多能装载 5 个古董

问题2:零钱兑换

假设有 25 分、10 分、5 分、1 分的硬币,现要找给客户 41 分的零钱,如何办到硬币个数最少?

贪心策略: 每一次都优先选择面值最大的硬币

① 选择 25 分的硬币,剩 16 分
② 选择 10 分的硬币,剩 6 分
③ 选择 5 分的硬币,剩 1 分
④ 选择 1 分的硬币
最终的解是共 4 枚硬币
25 分、10 分、5 分、1 分硬币各一枚

贪心策略的缺陷(换零钱2)

在这里插入图片描述

贪心注意点

贪心策略并不一定能得到全局最优解

因为一般没有测试所有可能的解,容易过早做决定,所以没法达到最佳解
贪图眼前局部的利益最大化,看不到长远未来,走一步看一步
优点:简单、高效、不需要穷举所有可能,通常作为其他算法的辅助算法来使用

缺点:鼠目寸光,不从整体上考虑其他可能,每次采取局部最优解,不会再回溯,因此很少情况会得到最优解

0-1背包问题

在这里插入图片描述
0-1背包:每件物品最多只能选择一件

0-1 背包 - 实例

在这里插入图片描述

package 贪心算法.背包问题;

import java.util.Arrays;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;

public class Knapsack {
    public static void main(String[] args) {
        select("价值主导", (Article a1, Article a2) -> {
            // 价值大的优先
            return a2.value - a1.value;
        });
        select("重量主导", (Article a1, Article a2) -> {
            // 重量小的优先
            return a1.weight - a2.weight;
        });
        select("价值密度主导", (Article a1, Article a2) -> {
            // 价值密度大的优先
            return Double.compare(a2.valueDensity, a1.valueDensity);
        });
    }

    static void select(String title,Comparator<Article> cmp) {
        Article[] articles = new Article[]{
                new Article(35, 10), new Article(30, 40),
                new Article(60, 30), new Article(50, 50),
                new Article(40, 35), new Article(10, 40),
                new Article(25, 30)
        };

        
        //1.容量
        int capacity = 150;
        int weight = 0;
        int value = 0;
        //2.贪心 排序
        Arrays.sort(articles, cmp);  //按照value降序
        //3.容器 装 选出来的article
        List<Article> selectedArticles = new LinkedList<>();
        //4.贪心算法
        for (int i = 0; i < articles.length && weight < capacity; i++) {
            int newWeight = weight + articles[i].weight;
            if(newWeight < capacity){
                weight = newWeight;
                value += articles[i].value;
                selectedArticles.add(articles[i]);
            }
        }
        System.out.println("【价值主导】");
        System.out.println("总价值 =" + value);
        System.out.println(selectedArticles);
        System.out.println("---------------");


    }

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值