Algorithm 如何解决这个编程竞赛练习
我偶然发现了这个算法问题,我找不到比暴力更好的方法了,有人能指导我吗 给定一个M*N的字符网格(a,B)。你可以任意翻动 列数,即将A更改为B和B更改为A。最大值是多少 在所有可能的翻转之后可以具有相同符号的行数 例如 如果我们翻转第1列和第3列,答案是2。如果需要进一步解释,请告诉我。我有一个Algorithm 如何解决这个编程竞赛练习,algorithm,Algorithm,我偶然发现了这个算法问题,我找不到比暴力更好的方法了,有人能指导我吗 给定一个M*N的字符网格(a,B)。你可以任意翻动 列数,即将A更改为B和B更改为A。最大值是多少 在所有可能的翻转之后可以具有相同符号的行数 例如 如果我们翻转第1列和第3列,答案是2。如果需要进一步解释,请告诉我。我有一个O(n^2)和O(M)解决方案,但比bruteforce略好,因为第二个循环开始于第一个循环的I+1,请告诉我您对此有何看法: 首先,我们需要更改位矩阵的A,B矩阵,其中每一行都是二进制矩阵,矩阵变成:
O(n^2)
和O(M)
解决方案,但比bruteforce略好,因为第二个循环开始于第一个循环的I+1
,请告诉我您对此有何看法:
首先,我们需要更改位矩阵的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];
}
给定N和M;
int maxSameSymbole[M]={0};
for(int i=0;imax)
max=maxSameSymbole[i];
}
希望这有助于找到更好的解决方案。从第一列开始,获取如果翻转该列,将具有相同符号的行的索引。例如:(1,4,9)行工作。为每一列获取这些索引,并将它们作为键放在一个映射中,该映射将索引列表映射到它发生的数字。最高的值就是答案。首先,请注意,
aba
和bab
在这个问题上本质上是相同的:每当一个被翻转到所有A
s时,另一个被翻转到所有B
s,反之亦然,因此这两个都同时计算答案。
另一方面,当翻转aba
或bab
使其包含相同的字母时,所有其他可能的行包含不同的字母
因此,建议的第一步是翻转以aB
开头的所有行,因为它将同时合并计算答案的行对
现在,我们有
A B A|
A B A| (flipped from B A B)
A B B|
A A B| (flipped from B B A)
剩下的就是找到最常出现的一行。
这可以通过构造一个映射来实现,该映射将行映射到它们的出现次数。
例如,它看起来像{aba
:2,abb
:1,aba
:1}
现在,
aba
显然赢了,因为它出现了两次,所以我们用B
s翻转该行中的所有列。使用A
s翻转所有列是另一个选项。@PieterGeerkens:在示例中,有4行,但解决方案是2行?使用动态规划@PieterGeerkens:您如何在示例中翻转以获得四行相同的符号?@G.Bach我尝试了DP方法,但不明白可以使用什么递归关系,是按列还是按行?@G.Bach您能把它作为一个答案并解释一下吗?我想知道如何比O(m*n)更好地解决它。@PieterGeerkens我不明白你在说什么;问题很清楚:给定一个矩阵,通过翻转任意数量的列来找出可以使所有符号完全相同的最大行数。很抱歉响应太晚,但我意识到这个算法是O(NM^2)。因为即使是布尔检查条件也需要O(N)时间。你能推荐一些更好的方法吗?由于问题的约束条件是M,因此这是一个比以前接受的解决方案更好的解决方案。它是O(MN)
A B A|
A B A| (flipped from B A B)
A B B|
A A B| (flipped from B B A)