当前位置:   article > 正文

篮球比赛分组问题(动态规划)_篮球队员的总人数为10,他们分成两个队伍。教练希望2个队伍的战斗力差值能够尽可能

篮球队员的总人数为10,他们分成两个队伍。教练希望2个队伍的战斗力差值能够尽可能

篮球(5V5)比赛中,每个球员拥有一个战斗力,每个队伍的所有球员战斗力之和为该队伍的总体战斗力。现有10个球员准备分为两队进行训练赛,教练希望2个队伍的战斗力差值能够尽可能的小,以达到最佳训练效果。给出10个球员的战斗力,如果你是教练,你该如何分队,才能达到最佳训练效果?请输出该分队方案下的最小战斗力差值。

输入描述:

10个篮球队员的战斗力(整数,范围[1,10000]),战斗力之间用空格分隔,如:10 9 8 7 6 5 4 3 2 1

不需要考虑异常输入的场景。

输出描述:

最小的战斗力差值,如:1

示例1

输入

10 9 8 7 6 5 4 3 2 1

输出

1

说明

1 2 5 9 10分为一队,3 4 6 7 8分为一队,两队战斗力之差最小,输出差值1。备注:球员分队方案不唯一,但最小战斗力差值固定是1。

这是一道动态规划的问题,难度较高,而且因为要求均分2组,还不太好转化为典型的背包问题。

在知道这是一道动态规划问题之前,我给出了自己的解法(目前我认为这个解法应该是错误的,但暂时还没有找到可以推翻这种解法的测试用例,所以暂时保留了这个解法)。

其基本思路为:

1.首先将队员按照战斗力排序;

2.为了保证战斗力均衡,可以得到战斗力最强的和最弱的必然分到一组,于是得到第一个小的分组(最强和最弱),期战斗力之和为SA,分到A组

3.在剩下的队伍当中两两组合,寻找战斗力最接近SA的组合,分到B组,其战斗力之和为SB,然后寻找最大最小的组合,然后更新SA(或者SB,这个需要在中间比较,看这个组合是放到SA合适还是SB合适),然后在剩下的组合当中寻找两两组合,使得SA和SB的差值最小,直到最后一组;

4.最后一组需要特殊处理一下,因为可能只有2个队员了,此时需要根据SA和SB的值,合理分配成员,最终得到分组结果。

代码为:

  1. //author:autumoon
  2. //联系QQ:4589968
  3. //日期:2021-12-27
  4. int LeastGapGroup()
  5. {
  6. int count = 10;
  7. vector<int> vValues;
  8. do
  9. {
  10. int val;
  11. cin >> val;
  12. if (val >= 1 && val <= 1e4)
  13. {
  14. vValues.push_back(val);
  15. }
  16. } while (vValues.size() < count);
  17. std::sort(vValues.begin(), vValues.end());
  18. std::vector<int> vFlag;
  19. for (int i = 0; i < 10; ++i)
  20. {
  21. vFlag.push_back(-1);
  22. }
  23. //max min together
  24. vFlag[0] = 0;
  25. vFlag[9] = 0;
  26. int nGapMin = 0;
  27. for (int i = 0; i < 10; ++i)
  28. {
  29. nGapMin += vValues[i];
  30. }
  31. //fenbie liangzu sum
  32. int nSum[2] = { 0 };
  33. nSum[0] = vValues[0] + vValues[9];
  34. nSum[1] = 0;
  35. //
  36. int nCurIndex = 1;
  37. //left
  38. vector<int> vLeftValues = GetLeftVector(vValues, vFlag);
  39. int nLeftCount = vLeftValues.size();
  40. do
  41. {
  42. //zhao b dui
  43. nLeftCount = vLeftValues.size();
  44. nGapMin = 0;
  45. for (int i = 0; i < nLeftCount; ++i)
  46. {
  47. nGapMin += vLeftValues[i];
  48. }
  49. int nSelIndex1 = -1;
  50. int nSelIndex2 = -1;
  51. for (int i = 0; i < nLeftCount; ++i)
  52. {
  53. int nSel1 = vLeftValues[i];
  54. for (int j = i + 1; j < nLeftCount; ++j)
  55. {
  56. int nSel2 = vLeftValues[j];
  57. int nTmp = nSel1 + nSel2 + nSum[nCurIndex];
  58. if (abs(nTmp - nSum[!nCurIndex]) < nGapMin)
  59. {
  60. nGapMin = abs(nTmp - nSum[!nCurIndex]);
  61. nSelIndex1 = i;
  62. nSelIndex2 = j;
  63. }
  64. }
  65. }
  66. if (nSelIndex1 != -1 && nSelIndex2 != -1)
  67. {
  68. vFlag[nSelIndex1] = 1;
  69. vFlag[nSelIndex2] = 1;
  70. nSum[nCurIndex] += vLeftValues[nSelIndex1] + vLeftValues[nSelIndex2];
  71. //zuida he zuixiao gei A ? B
  72. vFlag.clear();
  73. for (int i = 0; i < vLeftValues.size(); ++i)
  74. {
  75. vFlag.push_back(-1);
  76. }
  77. if (vLeftValues.size() > 2)
  78. {
  79. //jueding gei shui
  80. nCurIndex = nSum[nCurIndex] < nSum[!nCurIndex] ? nCurIndex : !nCurIndex;
  81. vFlag[0] = nCurIndex;
  82. vFlag[vLeftValues.size() - 1] = nCurIndex;
  83. nSum[nCurIndex] += vLeftValues[0] + vLeftValues[vLeftValues.size() - 1];
  84. vLeftValues = GetLeftVector(vLeftValues, vFlag);
  85. nLeftCount = vLeftValues.size();
  86. nCurIndex = !nCurIndex;
  87. }
  88. else if (vLeftValues.size() == 2)
  89. {
  90. //yibianjiayige
  91. if (abs(nSum[nCurIndex] + vLeftValues[0] - (nSum[!nCurIndex] + vLeftValues[1])) < abs(nSum[!nCurIndex] + vLeftValues[1] - (nSum[nCurIndex] + vLeftValues[0])))
  92. {
  93. nSum[nCurIndex] += vLeftValues[0];
  94. nSum[!nCurIndex] += vLeftValues[1];
  95. }
  96. else
  97. {
  98. nSum[!nCurIndex] += vLeftValues[1];
  99. nSum[nCurIndex] += vLeftValues[0];
  100. }
  101. vLeftValues.clear();
  102. }
  103. }
  104. else
  105. {
  106. break;
  107. }
  108. } while (nLeftCount > 1);
  109. cout << abs(nSum[nCurIndex] - nSum[!nCurIndex]) << endl;
  110. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/article/detail/42470
推荐阅读
相关标签
  

闽ICP备14008679号