java贪心算法案例

1.零钱找回问题

这个问题在我们的日常生活中就更加普遍了。假设1元、2元、5元、10元、20元、50元、100元的纸币分别有c0, c1, c2, c3, c4, c5, c6张。现在要用这些钱来支付K元,至少要用多少张纸币?用贪心算法的思想,很显然,每一步尽可能用面值大的纸币即可。在日常生活中我们自然而然也是这么做的。在程序中已经事先将Value按照从小到大的顺序排好。

2.背包问题:

背包容量=50; w[]={10,20,30} ,p[]={60,100,120} 用贪心选择(10+20)<50,p=160,但这并不是最优解,事实上(20+30)=50,p=100+120=220.才是问题的解。对于01背包,贪心采用自上而下,拆分子问题的方式为:{物品1,物品2,物品3}—>{物品2,物品3}----{物品3}…它无法保证最终能将背包装满,部分闲置的背包空间使每千克背包空间的价值降低了.
对于该问题,我们应该采用自下而上的动态规划来求解,拆分子问题的 方式为:{物品1}-------->{物品1,物品2}------>{物品1,物品2,物品3}.在求解时,应比较,选择该物品和不选择该物品,所导致的最终方案,然后再做出最好选择,为了更快求出问题的解。动态规划还记忆了过程中产生的许多互相重叠的子问题的答案。

代码

import cn.hutool.core.collection.CollUtil;

import java.util.*;

/**
 * desc: 算法测试
 *
 * @author qts
 * @date 2023/7/19 0019
 */
public class AlgorithmTest {



    public static void main(String[] args) {
        // 测试找零钱
        //System.out.println(change(320));

        // 测试背包问题
        List> maps = new ArrayList<>();
        HashMap map = new HashMap();
        map.put("weight", 10f);
        map.put("value",60f);
        map.put("name", "物品1");
        maps.add(map);

        map = new HashMap();
        map.put("weight", 30f);
        map.put("value",120f);
        map.put("name", "物品3");
        maps.add(map);

        map = new HashMap();
        map.put("weight", 20f);
        map.put("value",100f);
        map.put("name", "物品2");
        maps.add(map);

        sortByUnitValue(maps);
        System.out.println("物品列表: "+maps);

        List backpack = backpack(50f, maps.toArray(new HashMap[3]));

        System.out.println("结果: "+backpack);

    }

    // 钱面值
    public static int[] moneys = {100, 50, 20, 10, 5, 2, 1};
    // 对应面值的数量
    public static int[] counts = {5, 3, 0, 1, 2, 0, 3};

    /**
     * 贪心算法: 找零钱
     * @param amount 金额
     */
    public static String change(int amount) {
        StringBuilder result = new StringBuilder(amount + " = ");

        for (int i = 0; i < moneys.length; i++) {
            if (amount <= 0) {
                break;
            }

            int curMoneyCount = Math.min(amount / moneys[i], counts[i]);

            amount = amount - curMoneyCount * moneys[i];
            if (curMoneyCount > 0) {
                if (i > 0) {
                    result.append(" + ");
                }
                result.append(curMoneyCount).append("张").append(moneys[i]);
            }

        }

        if (amount > 0) {
            return "无解";
        }

        return result.toString();
    }


    /**
     * 单位价值倒序
     * @param maps
     */
    private static void sortByUnitValue(List> maps) {
        CollUtil.sort(maps, new Comparator>() {
            @Override
            public int compare(HashMap o1, HashMap o2) {
                Float weight1 = (Float) o1.get("weight");
                Float value1 = (Float) o1.get("value");
                Float unitValue1 = value1/weight1; // 单位重量的价值

                Float weight2 = (Float) o2.get("weight");
                Float value2 = (Float) o2.get("value");
                Float unitValue2 = value2/weight2; // 单位重量的价值

                return (int) ((unitValue2 - unitValue1));
            }
        });
    }

    /**
     * 贪心算法: 背包问题
     * @param capacity 背包容量
     * @param maps 物品,从最优到最次排序
     * @return
     */
    public static List> backpack(Float capacity,HashMap[] maps) {
        List> result = new ArrayList>();

        for (int i = 0; i < maps.length; i++) {
            if (capacity <= 0) {
                break;
            }

            HashMap goods = maps[i];
            Float weight = (Float) goods.get("weight");// 重量
            Float value = (Float) goods.get("value");// 价值
            String name = (String) goods.get("name");// 名称

            Float unitValue = value/weight; // 单位重量的价值

            float min = Math.min(capacity, weight);

            capacity -= min;// 剩余背包容量

            HashMap map = new HashMap<>();
            map.put("weight",min);
            map.put("name",name);

            result.add(map);
        }

        return result;

    }

}

结果:
在这里插入图片描述

你可能感兴趣的:(java,贪心算法,开发语言)