如何解决这个编程竞赛练习

时间:2014-10-02 22:47:39

标签: algorithm

我偶然发现了这个算法问题,我无法获得比蛮力更好的方法,有人可以指导我吗?

  

给定M * N字符网格(A,B)。你可以翻转任何一个   列数,即将A更改为B,将B更改为A.最大值是多少   在所有可能的翻转之后可以具有相同符号的行数

例如,

A B A|
B A B|
A B B|
B B A|

答案是2,如果我们翻转第1列和第1列如果需要进一步说明,请告诉我。

3 个答案:

答案 0 :(得分:1)

我有一个O(n^2)O(M)解决方案但是比bruteforce好一点,因为第二个循环开始到第一个循环的i+1,请告诉我你对它的看法: / p>

首先,我们需要更改位矩阵的A,B矩阵,其中每一行都是矩阵成为的二进制:

0 1 0|
1 0 1|
0 1 1|
1 1 0|

现在这是基于按位" 010& 101 = 000"因此,如果存在可能使行匹配的列排列。

Given N and M;
int maxSameSymbole[M] = {0};
for (int i = 0; i < M; i++) {
    for (int j = i+1; j < M; j++) {
         if (!(line[i].toBinary & line[j].toBinary)) //this will equal 0 if there is a possible flip that will make the 2 rows with the same symbole
             maxSameSymbole[i]++;
    }
}

// Simple find max in the maxSameSymbole list :
int max = maxSameSymbole[0];
for (int i = 0; i < M; i++) {
    if (maxSameSymbole[i] > max)
        max = maxSameSymbole[i];
}

希望这有助于找到更好的解决方案。

答案 1 :(得分:1)

从第一列开始,如果翻转该列,则获取具有相同符号的行的索引。例如:(1,4,9)行工作。为每个列获取这些索引,并将它们作为键映射到映射列表中的键,并将索引列表映射到它出现的数字。最高的价值就是答案。

答案 2 :(得分:1)

首先请注意,A B AB A B对于此问题的目的基本相同:每当有人翻转到所有A时,另一个被翻转到所有B 1}} s,反之亦然,所以两者同时计算答案。 另一方面,当翻转A B AB A B以使其包含相同的字母时,所有其他可能的行都包含不同的字母。

因此,第一个建议的步骤是翻转以B开头的所有,因为它将合并同时计算答案的行对。

现在,我们有

A B A|
A B A|  (flipped from B A B)
A B B|
A A B|  (flipped from B B A)

剩下的是找到最常出现的行。 这可以通过构建一个映射来完成,该映射将行映射到它们出现的次数。 例如,它看起来像{A B A:2,A B B:1,A A B:1}`。

现在,A B A显然赢了,因为它出现了两次,所以我们在该行中翻转了B个所有列。使用A翻转所有列是另一种选择。