简体   繁体   English

如何为两支球队相互比赛找到最佳解决方案?

[英]How to find an optimal solutions for 2 teams playing against each other?

I am given a table of teams A and B where for each pair of 2 players there is number.我得到了一张 A 队和 B 队的表格,其中每对 2 名球员都有一个数字。 The rows represent players of players of team A and columns of players of the team B. If a number is positive, it means that the player A is better than the plyaer from the B team and vice versa if negative.行代表A队球员的球员,B队球员的列。如果数字为正,则表示球员A优​​于B队的球员,如果为负,则反之亦然。

For example:例如:

-710 415 527 -641 175 48
-447 -799 253 626 304 895
509 -523 -758 -678 -689 92
24 -318 -61 -9 174 255
487 408 696 861 -394 -67

Both teams know this table.两支球队都知道这张桌子。 Now, what is done is that the team A reports 5 players, the team B can look at them and choose the best 5 players for them.现在做的就是A队报5名队员,B队可以看他们,为他们选择最好的5名队员。 If we want to compere the teams we sum up the numbers on the given positions from the table knowing that each team has a captain who is counted twice (as if a team had 6 players and the captain is there twice), if the sum is positive, the team A is better.如果我们想对球队进行比赛,我们将表中给定位置的数字相加,知道每支球队都有一名队长,他被计算两次(好像一支球队有 6 名球员,队长在场两次),如果总和是积极,A队更好。

The input are numbers a (the number of rows/players A) and b (columns/players B) and the table like this:输入是数字a (行数/玩家 A)和b (列/玩家 B)以及如下表格:

6
6
-54 -927 428 -510 911 93
-710 415 527 -641 175 48
-447 -799 253 626 304 895
509 -523 -758 -678 -689 92
24 -318 -61 -9 174 255
487 408 696 861 -394 -67

The output should be 1282.输出应为 1282。

So, what I did was that I put the numbers into a matrix like this:所以,我所做的是将数字放入这样的矩阵中:

a, b = int(input()), int(input())

matrix = [list(map(int,input().split())) for _ in range(a)]

I used a MinHeap and a MaxHeap for this.为此,我使用了 MinHeap 和 MaxHeap。 I put the rows into the MaxHeap because A team wants the biggest, then I get 5 best A players from it as follows:我将行放入 MaxHeap 因为 A 团队想要最大的,然后我从中得到 5 个最好的 A 球员,如下所示:

for player, values in enumerate(matrix):
    maxheap.enqueue(sum(values), player)

playersA = []
overallA = 0

for i in range(5):
    ov, pl  = maxheap.remove_max()
    if i == 0: # it is a captain
        playersA.append(pl)
        overallA += ov
        
    playersA.append(pl)
    overallA += ov

The B team knowing the A players the uses the MinHeap to find its best 5 players:知道 A 球员的 B 队使用 MinHeap 找到它最好的 5 名球员:

for i in range(b):
    player = []
    ov = 0
    for j in range(a): #take out a column of a matrix
        player.append(matrix[j][i])


    for rival in playersA: #counting only players already chosen by A
        ov += player[rival]

    minheap.enqueue(ov,i)

playersB = []
overallB = 0

for i in range(5):
    ov, pl = minheap.remove_min()
    if i == 0:
        playersB.append(pl)
        overallB += ov
        
    playersB.append(pl)
    overallB += ov

Having the players, then I count the sum from the matrix:有了球员,然后我计算矩阵中的总和:

out = 0
for a in playersA:
    for b in playersB:
        out += matrix[a][b]
print(out)

However, this solution doesn't give the right solutions always.但是,此解决方案并不总是提供正确的解决方案。 For example, it does for the input:例如,它对输入执行以下操作:

10
10
-802 -781 826 997 -403 243 -533 -694 195 182
103 182 -14 130 953 -900 43 334 -724 716
-350 506 184 691 -785 742 -303 -682 186 -520
25 -815 475 -407 -78 509 -512 714 898 243
758 -743 -504 -160 855 -792 -177 747 188 -190
333 -439 529 795 -500 112 625 -2 -994 282
824 498 -899 158 453 644 117 598 432 310
-799 594 933 -15 47 -687 68 480 -933 -631
741 400 979 -52 -78 -744 -573 -170 882 -610
-376 -928 -324 658 -538 811 -724 848 344 -308

But it doesn't for但它不为

11
11
279 475 -894 -641 -716 687 253 -451 580 -727 -509
880 -778 -867 -527 816 -458 -136 -517 217 58 740
360 -841 492 -3 940 754 -584 715 -389 438 -887
-739 664 972 838 -974 -802 799 258 628 3 815
952 -404 -273 -323 -948 674 687 233 62 -339 352
285 -535 -812 -452 -335 -452 -799 -902 691 195 -837
-78 56 459 -178 631 -348 481 608 -131 -575 732
-212 -826 -547 440 -399 -994 486 -382 -509 483 -786
-94 -983 785 -8 445 -462 -138 804 749 890 -890
-184 872 -341 776 447 -573 405 462 -76 -69 906
-617 704 292 287 464 -711 354 428 444 -42 45

So the question is: Can it be done like this or is there another fast algorithm ( O(n ** 2 ) / O(n ** 3) etc.), or I just gave to try all the possible combinations using brute force in O(n!) time complexity?所以问题是:可以这样完成还是有另一种快速算法(O(n ** 2 ) / O(n ** 3) 等),或者我只是尝试使用蛮力尝试所有可能的组合O(n!) 时间复杂度?

There is a way to do that with a polynomial complexity.有一种方法可以使用多项式复杂度来做到这一点。

To show you why your solution doesn't work, let's consider an other simpler problem.为了向您展示为什么您的解决方案不起作用,让我们考虑另一个更简单的问题。 Let's say each team only choose 2 players and there is no captain.假设每支球队只选择 2 名球员,没有队长。

Let's also take a simple score matrix:我们还采用一个简单的分数矩阵:

1 1 1 2 1 1 1 1 2 1
1 1 1 1 1 1 1 1 1 1
0 3 0 2 0 0 3 0 2 0
0 0 0 0 4 0 0 0 0 4
0 0 0 0 4 0 0 0 0 4

Here you can see that team A has no chance to win (as there are no negative numbers), but still they are going to try their best.在这里你可以看到 A 队没有获胜的机会(因为没有负数),但他们仍然会尽力而为。 Who should they pick?他们应该选谁?

Using your algorithm, team A should pick their best players and their ranking would be:使用你的算法,A 队应该选择他们最好的球员,他们的排名是:

pa0 < pa1 = pa2 < pa3 = pa4 pa0 < pa1 = pa2 < pa3 = pa4

If they choose pa3 and pa4, who both have a score of 4 (which is bad, but not as bad as pa0's score of 6), team B will win by 8 (they will choose pb4 and an other player who doesn't matter).如果他们选择 pa3 和 pa4,他们的得分都为 4(这很糟糕,但不如 pa0 的得分为 6),那么 B 队将以 8 分获胜(他们将选择 pb4 和其他无关紧要的球员) )。

On the other hand, if team A chose pa0 and pa1 (who are worse than pa3 and pa4 by your metric), the best team B can get is winning by 5 (if they choose pb3 and any other player)另一方面,如果 A 队选择了 pa0 和 pa1(根据你的指标,他们比 pa3 和 pa4 差),那么 B 队可以获得的最好的胜率是 5(如果他们选择 pb3 和任何其他球员)

Basically, your approximation fails to take into consideration that team B can only choose two players and thus can't take advantage of the pa0+pa1 weakness while it can easily exploit pa3+pa4's one.基本上,您的近似没有考虑到 B 队只能选择两名球员,因此无法利用 pa0+pa1 的弱点,而可以轻松利用 pa3+pa4 的弱点。

A better solution would be for team A to evaluate each player's score only by taking into account their 2 worst scores (or 5 if 5 players are to be selected): this would make the ranking as such:更好的解决方案是让 A 队仅通过考虑他们的 2 个最差分数(如果要选择 5 个球员,则为 5 个)来评估每个球员的分数:这将使排名如下:

pa2 < pa3 = pa4 < pa0 < pa1 pa2 < pa3 = pa4 < pa0 < pa1

Still it would be an approximation: some combinations like pa2+pa3 are actually not as bad as they sound as, once again, the weaknesses are spread enough that team B can't exploit them all (although for this very example the approximation yields the best result).这仍然是一个近似值:一些像 pa2+pa3 这样的组合实际上并没有听起来那么糟糕,再次说明,弱点传播得足够多,以至于 B 队无法利用它们(尽管对于这个例子,近似值产生了最好的结果)。

What we really need to pick is not the two best players, but the best combination of two players, and sadly there is no way I know of other than trying all the $s!/(k!(sk)!)$ combinations of k players among s (the size of the team).我们真正需要选择的不是两个最好的球员,而是两个球员的最佳组合,可悲的是,除了尝试所有 $s!/(k!(sk)!)$ 组合之外,我所知道的别无他法s(团队规模)中的 k 名球员。 It is not so bad, though, as for k=2 that's only $s*(s-1)/2$ and for k=5 that's $s*(s-1) (s-2) (s-3)*(s-4)/5!$, which is still polynomial in complexity despite being in O(s^5).不过,它并没有那么糟糕,对于 k=2 这只是 $s*(s-1)/2$ 而对于 k=5 那是 $s*(s-1) (s-2) (s-3) *(s-4)/5!$,尽管在 O(s^5) 中,但其复杂度仍然是多项式。 Adding a captain to the mix only multiplies the number of combinations by k.将队长添加到组合中只会将组合数乘以 k。 It also requires a twist on how to calculate the score but you should be able to find that.它还需要对如何计算分数进行一些修改,但您应该能够找到它。

Now that team A have selected their players, team B have the easy job to select theirs.现在 A 队已经选择了他们的球员,B 队可以轻松地选择他们的球员。 This is way simpler as here each player can be chosen individually.这更简单,因为这里可以单独选择每个玩家。


example of how this last algorithm should work with the score matrix provided in the beginning.最后一个算法应该如何与开头提供的分数矩阵一起工作的示例。

team A has 10 possible combinations: pa0+pa1, pa0+pa2, pa0+pa3, pa0+pa4, pa1+pa2, pa1+pa3, pa1+pa4, pa2+pa3, pa2+pa4, pa3+pa4. A队有10种可能的组合:pa0+pa1、pa0+pa2、pa0+pa3、pa0+pa4、pa1+pa2、pa1+pa3、pa1+pa4、pa2+pa3、pa2+pa4、pa3+pa4。 Their respective scores are: 5, 8, 7, 7, 7, 6, 6, 7, 7, 8.他们各自的分数是:5, 8, 7, 7, 7, 6, 6, 7, 7, 8。

The best combination is pa0+pa1, so that's what they send to team B.最好的组合是pa0+pa1,所以这就是他们发给B队的。

Team B calculate each of its player's score against pa0+pa1: pb0:2, pb1:2, pb2:2, pb3:3, pb4:2. B 队计算每个球员对 pa0+pa1 的得分:pb0:2, pb1:2, pb2:2, pb3:3, pb4:2。 pb3 is the best, all the others are equals, thus team B sends pb3+pb4 (for example), and the "answer" is 5. pb3 最好,其他都相等,因此 B 队发送 pb3+pb4(例如),“答案”为 5。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM