张昌蒲 严教 卡牌计算器

打印 上一主题 下一主题

主题 911|帖子 911|积分 2733

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

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

科技颠覆者

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表