1.描述
玩过三国杀的朋友应该都知道有个将叫张昌蒲,他会随机给出N张卡牌,卡牌的点数在1-13之间,可能重复。现在要求把卡牌分为两堆,两边卡牌的点数之和必须相等,要求两堆的卡牌数之和尽量多。
针对这个逻辑,我自己写了一些JAVA的实现,经过测试可行,下面给出代码,有兴趣的朋友可以看看,有改进的地方欢迎指出!
2.代码如下
计算分配方式的代码:- 1 public class CalculateCard {
- 2
- 3 public static void main(String[] args) {
- 4 Scanner scanner = new Scanner(System.in);
- 5 System.out.println("请输入严教牌,按点数,以空格割开,如(13 11 10):");
- 6 String input = scanner.nextLine();
- 7 System.out.println(input);
- 8 String[] inputCards = input.split(" ");
- 9 List<Integer> list = new ArrayList<>();
- 10 try {
- 11 Arrays.stream(inputCards).forEach(card -> list.add(Integer.parseInt(card)));
- 12 }catch (NumberFormatException e) {
- 13 System.out.println("请输入数字,牌的点数在1-13");
- 14 }
- 15 AtomicBoolean isCorrect = new AtomicBoolean(true);
- 16 list.forEach(item -> isCorrect.set(item <= 13 && item >= 1));
- 17 if(!isCorrect.get()){
- 18 System.out.println("----请输入数字,牌的点数在1-13");
- 19 }
- 20 calculateAll(list);
- 21 }
- 22
- 23 /**
- 24 * 计算所有可能的分配方式,并找到使用卡牌最多的组合方式
- 25 * @param list 所有输入的数字
- 26 */
- 27 private static void calculateAll(List<Integer> list){
- 28 List<Pair<Integer,Pair<String,String>>> okResult = new ArrayList<>();
- 29 List<Pair<Integer,Pair<String,String>>> okResultLast = new ArrayList<>();
- 30 List<Pair<Integer,Pair<Integer,String>>> result = new ArrayList<>();
- 31 //获取所有的数字组合方式
- 32 getAllComb(list,result);
- 33 int countNum = 0;
- 34 //遍历所有组合方式
- 35 for (int i = 0; i < result.size(); i++) {
- 36 /*
- 37 * 思路
- 38 * 1.取出其中一种组合,拿到这个组合的点数和sum
- 39 * 2.将当前组合中的所有数字放在一个List--currentList中
- 40 * 3.从原来得包含所有点数的卡牌集合中筛选出去掉currentList所有数字的其他数字,放在listLeft中
- 41 * 5.获得listLeft中所有数字的全部组合方式,放在result1中
- 42 * 6.遍历result1,比对总和与sum是否相等,相等则为一种成功的组合方式。
- 43 * 7.找到成功组合中使用卡牌最多的组合方式
- 44 */
- 45 Pair<Integer,Pair<Integer,String>> pair = result.get(i);
- 46 int sum = pair.getValue().getKey();
- 47 int numCount = pair.getKey();
- 48 String com = pair.getValue().getValue();
- 49 String[] numStr = com.split(",");
- 50 List<Integer> listLeft = new ArrayList<>();
- 51 List<Integer> currentList = new ArrayList<>();
- 52 for (int j = 0; j < numStr.length; j++) {
- 53 currentList.add(Integer.parseInt(numStr[j]));
- 54 }
- 55 for (int j = 0; j < list.size(); j++) {
- 56 if(!currentList.contains(list.get(j))) listLeft.add(list.get(j));
- 57 }
- 58 List<Pair<Integer,Pair<Integer,String>>> result1 = new ArrayList<>();
- 59 getAllComb(listLeft,result1);
- 60 for (int j = 0; j < result1.size(); j++) {
- 61 Pair<Integer,Pair<Integer,String>> pair1 = result1.get(j);
- 62 int leftSum = pair1.getValue().getKey();
- 63 int leftCount = pair1.getKey();
- 64 String com1 = pair1.getValue().getValue();
- 65 countNum = countNum == 0 ? numCount + leftCount : countNum;
- 66 if(leftSum == sum && countNum <= numCount + leftCount){
- 67 //计数,如果组合中的数字个数更大,则移除结果集,重新添加,只保存最多的
- 68 if(countNum != 0 && countNum < numCount+leftCount){
- 69 countNum = numCount + leftCount;
- 70 okResultLast.clear();
- 71 }
- 72 okResult.add(new Pair<>(numCount+leftCount,new Pair<>(com,com1)));
- 73 okResultLast.add(new Pair<>(numCount+leftCount,new Pair<>(com,com1)));
- 74 }
- 75 }
- 76 }
- 77 // System.out.println("所有组合:");
- 78 // for (int i = 0; i < okResult.size(); i++) {
- 79 // Pair<Integer,Pair<String,String>> resultPair = okResult.get(i);
- 80 // System.out.println("组合的总牌数:"+resultPair.getKey() +
- 81 // " ===>组合1为: " + resultPair.getValue().getKey() +
- 82 // " ===>组合2为: " + resultPair.getValue().getValue());
- 83 // }
- 84 System.out.println("=================================================");
- 85 System.out.println("使用卡牌最多的组合方式:");
- 86 System.out.println("=================================================");
- 87 for (int i = 0; i < okResultLast.size(); i++) {
- 88 Pair<Integer,Pair<String,String>> resultPair = okResultLast.get(i);
- 89 System.out.println("当前分配方"+i+"式总牌数:"+resultPair.getKey() +
- 90 "\n====>堆一卡牌点数分别为: " + resultPair.getValue().getKey() +
- 91 "\n====>堆二卡牌点数分别为: " + resultPair.getValue().getValue());
- 92 }
- 93 System.out.println("=================================================");
- 94 }
- 95
- 96 /**
- 97 * 获得所有可能的组合
- 98 * 如数字列表为:【1,2,3】
- 99 * 那么得到的所有组合为【1】,【2】,【3】,【1,2】,【1,3】,【2,3】,【1,2,3】
- 100 * @param list 所有数字
- 101 * @param result 返回的组合集合
- 102 */
- 103 private static void getAllComb(List<Integer> list,List<Pair<Integer,Pair<Integer,String>>> result){
- 104 List<String> com = new ArrayList<>();
- 105 for (int i = 1; i != list.size() + 1; i++) {
- 106 ComputCombinations.getCombination(result,list,0,i,com);
- 107 }
- 108 // result.stream().forEach(item -> System.out.println("数字数:"+ item.getKey()+
- 109 // "=====>总值:"+ item.getValue().getKey()+ " 内容:" + item.getValue().getValue()));
- 110 }
- 111
- 112 }
复制代码 计算数字组合方式的代码:- public static void getCombination(List<Pair<Integer,Pair<Integer,String>>> result,
- List<Integer> list, int start, int len , List<String> com){
- if(len == 0){
- String s = "";
- for (int i = 0; i != com.size() ; i++) {
- s = s.concat(com.get(i));
- }
- String comStr = s.substring(0,s.length() - 1);
- String[] all = comStr.split(",");
- AtomicInteger sum = new AtomicInteger();
- Arrays.stream(all).forEach(item -> sum.addAndGet(Integer.parseInt(item)));
- result.add(new Pair<>(com.size(),new Pair<>(sum.get(),comStr)));
- return;
- }
- if(start == list.size()){
- return;
- }
- com.add(list.get(start)+",");
- getCombination(result,list, start+1,len - 1,com);
- com.remove(com.size()-1);
- getCombination(result,list,start+1,len,com);
- }
复制代码 测试结果:

有可以改进的地方,欢迎指出...
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |