问题
商品总价 4800,共有以下几种充值赠送活动,问怎么充值购买最划算且最方便?
- 充值 200 赠送 10
- 充值 300 赠送 15
- 充值 500 赠送 25
- 充值 1000 赠送 50
- 充值 2000 赠送 100
- 充值 5000 赠送 250
实现
import java.util.*;
/**
* 商品总价 4800,问怎么充值购买最划算且最方便?
* 有以下优惠方案:
* 充值 200 赠送 10
* 充值 300 赠送 15
* 充值 500 赠送 25
* 充值 1000 赠送 50
* 充值 2000 赠送 100
* 充值 5000 赠送 250
*
* @author 杨贤达
* @date 2019-11-13
*/
public class Solution {
private static final Map<Integer, Integer> SOURCE = new LinkedHashMap<>();
private static final int TARGET = 4800;
private static Integer minNum = TARGET;
// 只是为了简单去重用,未实现排序逻辑
private static Set<List<Integer>> resultSet = new TreeSet<>((l1, l2) -> l1.containsAll(l2) && l2.containsAll(l1) ? 0 : 1);
static {
SOURCE.put(200, 10);
SOURCE.put(300, 15);
SOURCE.put(500, 25);
SOURCE.put(1000, 50);
SOURCE.put(2000, 100);
SOURCE.put(5000, 250);
}
public static void main(String[] args) {
fun(new ArrayList<>(), 0);
printResult(resultSet);
}
private static void printResult(Set<List<Integer>> resultSet) {
for (List<Integer> list : resultSet) {
Map<Integer, Integer> map = new HashMap<>();
for (Integer integer : list) {
if (map.containsKey(integer)) {
map.put(integer, map.get(integer) + 1);
} else {
map.put(integer, 1);
}
}
Integer actualPayment = list.stream().reduce(0, Integer::sum);
Integer totalAmount = list.stream().reduce(0, (a, b) -> a + b + SOURCE.get(b));
System.out.println("==================================================");
System.out.println("搭配集合 = " + map);
System.out.println("实际支付 = " + actualPayment);
System.out.println("实际支付 + 赠送金额 = " + totalAmount);
System.out.println("浪费金额 = " + (totalAmount - TARGET));
System.out.println("操作次数 = " + list.size());
}
}
private static void fun(List<Integer> list, int total) {
int waste = total - TARGET;
// 浪费超过 150 元,直接不予考虑
if (waste > 150) {
return;
}
// 必须大于指定金额,不能小于,即浪费的金额必须为正数
if (waste > 0 && waste < minNum) {
minNum = waste;
}
// 收集筛选后的结果
if (total - TARGET > 0 && total - TARGET < 150 && list.size() < 6) {
resultSet.add(list);
}
for (Map.Entry<Integer, Integer> entry : SOURCE.entrySet()) {
Integer key = entry.getKey();
Integer value = entry.getValue();
list.add(key);
List<Integer> copy = (List<Integer>) ((ArrayList<Integer>) list).clone();
total = total + key + value;
fun(copy, total);
list.remove(key);
total = total - key - value;
}
}
}
输出
==================================================
搭配集合 = {2000=2, 200=3}
实际支付 = 4600
实际支付 + 赠送金额 = 4830
浪费金额 = 30
操作次数 = 5
==================================================
搭配集合 = {2000=2, 200=2, 300=1}
实际支付 = 4700
实际支付 + 赠送金额 = 4935
浪费金额 = 135
操作次数 = 5
==================================================
搭配集合 = {2000=1, 500=1, 1000=2, 200=1}
实际支付 = 4700
实际支付 + 赠送金额 = 4935
浪费金额 = 135
操作次数 = 5
==================================================
搭配集合 = {2000=2, 500=1, 200=1}
实际支付 = 4700
实际支付 + 赠送金额 = 4935
浪费金额 = 135
操作次数 = 4
==================================================
搭配集合 = {2000=2, 200=3}
实际支付 = 4600
实际支付 + 赠送金额 = 4830
浪费金额 = 30
操作次数 = 5
==================================================
搭配集合 = {2000=1, 500=1, 1000=2, 200=1}
实际支付 = 4700
实际支付 + 赠送金额 = 4935
浪费金额 = 135
操作次数 = 5
==================================================
搭配集合 = {2000=1, 1000=2, 300=2}
实际支付 = 4600
实际支付 + 赠送金额 = 4830
浪费金额 = 30
操作次数 = 5
==================================================
搭配集合 = {2000=2, 300=2}
实际支付 = 4600
实际支付 + 赠送金额 = 4830
浪费金额 = 30
操作次数 = 4
==================================================
搭配集合 = {2000=2, 200=2, 300=1}
实际支付 = 4700
实际支付 + 赠送金额 = 4935
浪费金额 = 135
操作次数 = 5
==================================================
搭配集合 = {2000=1, 1000=2, 300=2}
实际支付 = 4600
实际支付 + 赠送金额 = 4830
浪费金额 = 30
操作次数 = 5
==================================================
搭配集合 = {2000=2, 200=3}
实际支付 = 4600
实际支付 + 赠送金额 = 4830
浪费金额 = 30
操作次数 = 5
==================================================
搭配集合 = {2000=2, 200=2, 300=1}
实际支付 = 4700
实际支付 + 赠送金额 = 4935
浪费金额 = 135
操作次数 = 5
==================================================
搭配集合 = {2000=1, 500=1, 1000=2, 200=1}
实际支付 = 4700
实际支付 + 赠送金额 = 4935
浪费金额 = 135
操作次数 = 5
==================================================
搭配集合 = {2000=2, 200=3}
实际支付 = 4600
实际支付 + 赠送金额 = 4830
浪费金额 = 30
操作次数 = 5