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<HashMap<String, Object>> maps = new ArrayList<>();HashMap<String, Object> map = new HashMap<String, Object>();map.put("weight", 10f);map.put("value",60f);map.put("name", "物品1");maps.add(map);map = new HashMap<String, Object>();map.put("weight", 30f);map.put("value",120f);map.put("name", "物品3");maps.add(map);map = new HashMap<String, Object>();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<HashMap<String, Object>> maps) {CollUtil.sort(maps, new Comparator<HashMap<String, Object>>() {@Overridepublic int compare(HashMap<String, Object> o1, HashMap<String, Object> 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<HashMap<String,Object>> backpack(Float capacity,HashMap<String,Object>[] maps) {List<HashMap<String,Object>> result = new ArrayList<HashMap<String, Object>>();for (int i = 0; i < maps.length; i++) {if (capacity <= 0) {break;}HashMap<String, Object> 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<String, Object> map = new HashMap<>();map.put("weight",min);map.put("name",name);result.add(map);}return result;}}
结果: