• java实现计算最优现金优惠券组合


    java实现计算最优现金优惠券组合

    在众多可叠加现金类型优惠券中(比如100减5,200减12等),选出可打折金额最大的组合。

    下面代码

    package com.dk.common.util.algo;
    
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    /**
     * 
     * 计算最优优惠券组合
     *
     */
    public class CalcDiscountCouponOptimalCombination {
    
    	/// ***** 测试
    	public static void main(String[] args) {
    
    		double max = 600;
    
    		List<Item> list = new ArrayList<>();
    		list.add(new Item(100, 2));
    		list.add(new Item(100, 3));
    		list.add(new Item(300, 3));
    		list.add(new Item(300, 9));
    		list.add(new Item(300, 4));
    		list.add(new Item(200, 4));
    		list.add(new Item(100, 2));
    		list.add(new Item(200, 9));
    		list.add(new Item(300, 4));
    		list.add(new Item(100, 3));
    		list.add(new Item(230, 3));
    
    		list.add(new Item(300, 3));
    		list.add(new Item(500, 9));
    		list.add(new Item(300, 4));
    		list.add(new Item(100, 4));
    		list.add(new Item(100, 2));
    		list.add(new Item(400, 9));
    		list.add(new Item(300, 4));
    		list.add(new Item(100, 3));
    		list.add(new Item(230, 3));
    
    		for (int i = 0; i < 5; i++) {
    			list.add(new Item(300, 3));
    			list.add(new Item(500, 9));
    			list.add(new Item(300, 4));
    			list.add(new Item(100, 4));
    			list.add(new Item(100, 2));
    			list.add(new Item(400, 9));
    			list.add(new Item(300, 4));
    			list.add(new Item(100, 3));
    			list.add(new Item(230, 3));
    			list.add(new Item(230, 3));
    		}
    
    		// ************************
    
    		// 券数量多的,建议先按“折扣限制”从大到小排序,可以减少逻辑计算时间
    		list.sort((o1, o2) -> o1.deduct == o2.deduct ? 0 : o1.deduct > o2.deduct ? -1 : 1);
    
    		Map<String, Double> maxReduceIdxIssMap = calcMaxReduceIdxIssMap(list, max);
    		System.out.println(maxReduceIdxIssMap);
    
    		for (String idxIss : maxReduceIdxIssMap.keySet()) {
    			System.out.println("-------------------------------------");
    			System.out.println(idxIss);
    
    			String[] idxIsArr = idxIss.split("");
    			for (int idx = 0; idx < idxIsArr.length; idx++) {
    				String is = idxIsArr[idx];
    				if ("1".equals(is)) {
    					System.out.println(idx + ": " + list.get(idx));
    				}
    			}
    
    		}
    
    	}
    
    	/**
    	 * 计算最大优惠组合列表
    	 */
    	public static Map<String, Double> calcMaxReduceIdxIssMap(List<Item> list, double maxAstrict) {
    		Map<String, Double> maxReduceIdxIssMap = new HashMap<>();// 统计极限组合
    
    		int len = list.size();
    		LoopRear lr = new LoopRear() {
    			double currMaxReduce = 0;
    
    			// idxIss 由0、1组成,1所在下标表示对应项参与了此组合
    			@Override
    			public boolean runRear(int start, String idxIss, double deductSum, double reduceSum) {
    				boolean haveRear = false;// 后面流程有没有符合条件的子类组合
    				String pad = "1";
    				for (int i = start; i < len; i++) {
    					Item item = list.get(i);
    					double currDeductSum = deductSum + item.deduct;// 当前组合折扣限制总和
    					double currReduceSum = reduceSum + item.reduce;// 当前组合折扣额度总和
    					if (currDeductSum <= maxAstrict) {
    						haveRear = true;// 当前组合限制总和小于总金额,表示当前组合的父类不是极限组合(存在子类组合)
    						String currIdxIss = idxIss + pad;
    						boolean haveRearRear = this.runRear(i + 1, currIdxIss, currDeductSum, currReduceSum);// 是否存在子类组合
    						if (!haveRearRear) {
    							// 不存在子类组合,表示当前组合为一个极限组合
    							// 比对之前的折扣金额,只保留最大折扣金额的
    							if (currReduceSum > currMaxReduce) {
    								currMaxReduce = currReduceSum;
    								maxReduceIdxIssMap.clear();
    								maxReduceIdxIssMap.put(currIdxIss, currReduceSum);
    							} else if (currReduceSum == currMaxReduce) {
    								maxReduceIdxIssMap.put(currIdxIss, currReduceSum);
    							}
    						}
    					}
    					pad = "0" + pad;// 前面下标的项不参与之后组合,后移一位
    				}
    				return haveRear;
    			}
    		};
    		lr.runRear(0, "", 0, 0);// 从第一个开始执行
    
    		return maxReduceIdxIssMap;
    	}
    
    	public static class Item {
    		protected double deduct;// 折扣限制,折扣条件
    		protected double reduce;// 折扣额度
    
    		public Item(double deduct, double reduce) {
    			super();
    			this.deduct = deduct;
    			this.reduce = reduce;
    		}
    
    		@Override
    		public String toString() {
    			return reduce + "[" + deduct + "]";
    		}
    	}
    
    	protected interface LoopRear {
    		boolean runRear(int start, String idxIss, double deductSum, double reduceSum);
    	}
    
    }
    
  • 相关阅读:
    zabbix
    Tomcat 部署Web应用
    WebLogic
    WebLogic部署集群和代理服务器
    WebLogic 中的基本概念
    GIT详解和GITHUB
    Tomcat 内存溢出对应解决方式
    apache和tomcat区别
    数据库介绍
    The superclass "javax.servlet.http.HttpServlet" was not found on the Java Build Path
  • 原文地址:https://www.cnblogs.com/dken/p/CalcDiscountCouponOptimalCombination.html
Copyright © 2020-2023  润新知