赞
踩
篮球(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的值,合理分配成员,最终得到分组结果。
代码为:
- //author:autumoon
- //联系QQ:4589968
- //日期:2021-12-27
-
- int LeastGapGroup()
- {
- int count = 10;
-
- vector<int> vValues;
-
- do
- {
- int val;
- cin >> val;
-
- if (val >= 1 && val <= 1e4)
- {
- vValues.push_back(val);
- }
-
- } while (vValues.size() < count);
-
- std::sort(vValues.begin(), vValues.end());
-
- std::vector<int> vFlag;
- for (int i = 0; i < 10; ++i)
- {
- vFlag.push_back(-1);
- }
-
- //max min together
- vFlag[0] = 0;
- vFlag[9] = 0;
-
- int nGapMin = 0;
- for (int i = 0; i < 10; ++i)
- {
- nGapMin += vValues[i];
- }
-
- //fenbie liangzu sum
- int nSum[2] = { 0 };
- nSum[0] = vValues[0] + vValues[9];
- nSum[1] = 0;
-
- //
- int nCurIndex = 1;
-
- //left
- vector<int> vLeftValues = GetLeftVector(vValues, vFlag);
- int nLeftCount = vLeftValues.size();
- do
- {
- //zhao b dui
- nLeftCount = vLeftValues.size();
-
- nGapMin = 0;
- for (int i = 0; i < nLeftCount; ++i)
- {
- nGapMin += vLeftValues[i];
- }
-
- int nSelIndex1 = -1;
- int nSelIndex2 = -1;
-
- for (int i = 0; i < nLeftCount; ++i)
- {
- int nSel1 = vLeftValues[i];
- for (int j = i + 1; j < nLeftCount; ++j)
- {
- int nSel2 = vLeftValues[j];
- int nTmp = nSel1 + nSel2 + nSum[nCurIndex];
- if (abs(nTmp - nSum[!nCurIndex]) < nGapMin)
- {
- nGapMin = abs(nTmp - nSum[!nCurIndex]);
- nSelIndex1 = i;
- nSelIndex2 = j;
- }
- }
- }
-
- if (nSelIndex1 != -1 && nSelIndex2 != -1)
- {
- vFlag[nSelIndex1] = 1;
- vFlag[nSelIndex2] = 1;
-
- nSum[nCurIndex] += vLeftValues[nSelIndex1] + vLeftValues[nSelIndex2];
-
- //zuida he zuixiao gei A ? B
- vFlag.clear();
- for (int i = 0; i < vLeftValues.size(); ++i)
- {
- vFlag.push_back(-1);
- }
-
- if (vLeftValues.size() > 2)
- {
- //jueding gei shui
- nCurIndex = nSum[nCurIndex] < nSum[!nCurIndex] ? nCurIndex : !nCurIndex;
-
- vFlag[0] = nCurIndex;
- vFlag[vLeftValues.size() - 1] = nCurIndex;
-
- nSum[nCurIndex] += vLeftValues[0] + vLeftValues[vLeftValues.size() - 1];
-
- vLeftValues = GetLeftVector(vLeftValues, vFlag);
-
- nLeftCount = vLeftValues.size();
-
- nCurIndex = !nCurIndex;
- }
- else if (vLeftValues.size() == 2)
- {
- //yibianjiayige
- if (abs(nSum[nCurIndex] + vLeftValues[0] - (nSum[!nCurIndex] + vLeftValues[1])) < abs(nSum[!nCurIndex] + vLeftValues[1] - (nSum[nCurIndex] + vLeftValues[0])))
- {
- nSum[nCurIndex] += vLeftValues[0];
- nSum[!nCurIndex] += vLeftValues[1];
- }
- else
- {
- nSum[!nCurIndex] += vLeftValues[1];
- nSum[nCurIndex] += vLeftValues[0];
- }
-
- vLeftValues.clear();
-
- }
- }
- else
- {
- break;
- }
-
-
- } while (nLeftCount > 1);
-
- cout << abs(nSum[nCurIndex] - nSum[!nCurIndex]) << endl;
- }

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。