2名球员团队知道最大动作

时间:2014-06-30 19:29:22

标签: c++ algorithm

给出了要玩2人游戏的N个玩家的列表。他们每个人都非常精通特定的举动,或者他们不是。找出双人球队可以知道的最大动作数。

并了解有多少团队可以知道最大移动次数?

示例如果a [i] [j]为1,我们有4个玩家和5个移动,第i个玩家精通第j个移动,否则为0。

10101
11100
11010 
00101

双人队可以知道的最大移动次数为5次,他们是两支可以知道最大移动次数的队伍。

解释 :( 1,3)和(3,4)知道所有5个动作。所以2人队所知道的最大动作是5,只有2支球队可以实现这一点。

我的方法:对于每对玩家,我会检查是否有任何玩家精通第i个移动,并且每个玩家保持最大对,他可以与其他玩家一起保持当地最大值移动组合。

vector<int> pairmemo;
for(int i=0;i<n;i++){
    int mymax=INT_MIN;
    int countpairs=0;
    for(int j=i+1;j<n;j++){
        int count=0;
            for(int k=0;k<m;k++){
                if(arr[i][k]==1 || arr[j][k]==1)
                {
                    count++;
                }
        }
        if(mymax<count){
            mymax=count;
            countpairs=0;
        }
        if(mymax==count){
            countpairs++;
        }

    }
    pairmemo.push_back(countpairs);
    maxmemo.push_back(mymax);
}

所有N个玩家的总体最大值是答案,而计数是计算对的相应总和。

for(int i=0;i<n;i++){
    if(maxi<maxmemo[i])
        maxi=maxmemo[i];
}

int countmaxi=0;

for(int i=0;i<n;i++){
    if(maxmemo[i]==maxi){
        countmaxi+=pairmemo[i];
    }
}

cout<<maxi<<"\n";
cout<<countmaxi<<"\n";

时间复杂度:O((N ^ 2)* M)

代码: 我该如何改进呢?

约束:N <= 3000且M <= 1000

3 个答案:

答案 0 :(得分:0)

如果用一个非常大的整数表示每组移动,问题归结为找到在MovesI OR MovesJ中设置了最大位数的一对玩家(I,J)。

因此,您可以使用位打包并压缩有关长整数数组中移动的所有信息。根据约束条件,需要存储16个无符号长整数。因此,对于每对玩家,您OR对应的数组并计算其数量。这将花费O(N ^ 2 * 16),在约束条件下运行速度非常快。

实施例: 让我们说给定的矩阵是

11010
00011

并使用4位整数进行打包。 它看起来像是:

1101-0000
0001-1000

13,0
1,8

OR 2个玩家团队的移动数组变为13,8之后,现在计算一个比特。您还必须优化位计数,因为读取了接受的答案here,否则因子M将出现在复杂性中。只需在处理对时维护一个count变量和一个maxNumberOfBitsSet变量。

答案 1 :(得分:0)

我做的是: 1.在所有可能的对之间进行逻辑或 - O(N^2)并将其存储在2D数组中,忽略对称对角线。 (多数民众赞成我们保存了一半的计算 - 参见示例) 2.找到2D阵列中的最大值(可以在执行任务1时完成) - &gt; O(1) 3.计算2D阵列中的多少个单元格等于任务2 O(N^2)

中的最大值

总和:2*O(N^2)+ O(1) => O(N^2)

示例(使用问题中的数据(带字母索引):

 A[10101] B[11100] C[11010] D[00101]

任务1:

[A|B] = 11101 = SUM(4)
[A|C] = 11111 = SUM(5)
[A|D] = 10101 = SUM(3)
[B|C] = 11110 = SUM(4)
[B|D] = 11101 = SUM(4)
[C|D] = 11111 = SUM(5)

任务2(完成时完成1):

Max = 5

任务3:

Count = 2

顺便说一句,O(N ^ 2)是最小可能的,因为你必须检查所有可能的对。

答案 2 :(得分:0)

由于您必须找到所有解决方案,除非您找到一种方法来查找计数而不实际找到解决方案,否则您必须实际查看或消除所有可能的解决方案。所以最坏的情况总是O(N ^ 2 * M),只要N和M都是大而且相似的大小,我就称之为O(n ^ 3)。

然而,您可以希望通过修剪在平均情况下获得更好的性能。 不要检查每个案例。找到消除组合而无需检查它们的方法。

我将总和并存储每个玩家已知的移动总数,并按该值对数组行进行排序。这应该提供一个简单的检查,以提前退出循环。 O(n log n)的排序在O(n ^ 3)算法中基本上是免费的。

使用Priyank的基本思想,除了bitsets,因为你显然不能使用3000位的固定整数类型。

您可以为列创建第二个位集数组,并将其用作修剪玩家的掩码。