以下是我的问题的可视化:
我需要找到存放在正方形中的最有价值的菱形。 我正在考虑这几天但直到现在,除了使用'for loop'并检查每个可能的菱形之外,我没有找到任何其他东西。你们怎么看待这个?这是我能做到的唯一方法吗? :P谢谢:)
答案 0 :(得分:1)
以下是我的想法:
第一次迭代,您遍历矩阵,但是对角线。你从最左上角开始,你可以适合你的菱形(或菱形的一面),你看看菱形大小所覆盖的元素。
我希望你能得到检查令。你对这些元素的处理是你总结: e(0,1)+ e(1,0)= 11 , e(0,2)+ e(1,1 )= 3 等等。你必须注意到,当你处理同一行上的元素(上面标有相同字母的元素)时,你不必再次计算总和:那里有一个元素外出,一个进入,所以你只访问两个元素来获得新的总和。
第二次迭代,您沿着对角线遍历矩阵,但是从另一侧。您从右上角开始,并处理先前计算的总和。因此,您要检查的第一对将位于(0,3),(1,4)。你做的事与以前完全相同:你再次计算金额。
现在,在第二次迭代结束时,每个处理过的字段实际上都包含稀疏菱形的总和,该字符在该字段中有一个上角。 3x3菱形的示例如下图所示:
第3步从图像中可以看出, n 的稀疏菱形是"缺少"另一个稀疏菱形 - 大小为(n-1)的菱形。迭代1和2正是为图像中所有大小为 n 的稀疏rhombs找到和的过程。因此,作为第3步,我们再次进行第1次和第2次迭代,但不是我们正在搜索的大小( n ),而是使用大小(n-1) )。 注意表示"搜索"对于大小1等于输入矩阵(例如,如果n = 2,对于第3步,你不必计算任何东西)。
最后,对于顶部位置(0,2)的3x3菱形感兴趣的总和是来自前两次迭代的(0,2)处的和,以及来自(1,2)的总和第三步。您可以将这两个加在一起:对于位置(x,y)的前两个过程的结果矩阵中的每个元素,可以在第3步结果矩阵的位置(x,y + 1)添加元素。 现在你只需找到最大值,你就可以得到关于菱形的最大值和位置的答案。
你在4次传球中完成所有这些操作(你可以在计算第2次传球时跟踪最大值) - 所以这会给出O(4*n^2) = O(n^2)
的复杂性,其中n
的大小是广场的大小。
希望它清楚,如果我弄清楚了我的答案,请要求澄清。
2x2菱形的示例
第一次通过
-1 11 3 7 5 * / * * *
-1 9 14 12 3 / * * * *
-1 12 18 4 6 * * * * *
-1 11 3 6 2 * * * * *
-1 -1 -1 -1 -1 * * * * *
第二遍
-1 25 15 10 -1 * * * \ *
-1 27 18 18 -1 * * * * \
-1 15 24 6 -1 * * * * *
-1 -1 -1 -1 -1 * * * * *
-1 -1 -1 -1 -1 * * * * *
第3步
由于 n = 1 ,第3遍不需要计算任何东西,第三遍的输出是输入矩阵
1 2 2 2 2
9 1 5 3 1
8 9 9 2 3
3 9 2 3 1
2 1 3 1 1
现在,我们只需要将第二次迭代的输出与第三步的输出相加(向上移动一位)。我们得到:
-1 26 20 13 -1
-1 36 27 20 -1
-1 24 26 9 -1
-1 -1 -1 -1 -1
-1 -1 -1 -1 -1
<强>答案强> 在(1,1)处有一个上角的菱形是最有价值的一个,总和为31。
注意: -1
是一个菱形边不适合的地方 - undefined sum。您可以在程序中以您想要的方式标记它(特别是如果您的矩阵中实际上可以有负值)。在第二遍中,您可以将具有 undifined 元素的任何总和设置为 undifined 。
注意2:无论菱形大小是什么,当你通过矩阵滑动菱形边时,一个数字总是进来而另一个数字来自总和(除非你和#39;重新进入新行。)
注3:第2次和第2次通过中菱形的第一个位置在数组中标有/
或\
示例3x3菱形
让我在同一个矩阵上做3x3菱形,以表明复杂度为O(n^2)
(其中n
是方形大小的大小),一般情况下不是仅适用于2x2菱形。
让我们调用输入矩阵z[][]
,即第一遍f[][]
后的矩阵,以及第二遍后的矩阵s[][]
第一次通过
f[0][2] = z[0][2] + z[1][1] + z[2][0] == 11
(a) f[0][3] = z[0][3] + z[1][2] + z[2][1] == 16
(b) f[1][2] = f[0][3] - z[0][3] + z[3][0] == 17
(b) f[0][4] = z[0][4] + z[1][3] + z[2][2] == 14
(c) f[1][3] = f[0][4] - z[0][4] + z[3][1] == 21
(c) f[2][2] = f[1][3] - z[1][3] + z[4][0] == 20
(c) f[1][4] = z[1][4] + z[2][3] + z[3][2] == 5
(d) f[2][3] = f[1][4] - z[1][4] + z[4][1] == 5
(d) f[2][4] = z[2][4] + z[3][3] + z[4][2] == 9
(e) 您最多访问一次元素。标有不同字母的是同一行的总和。在该行的第一个总和中,您必须将与菱形边相同的元素相加,我们将其称为m
菱形m x m
。在该行的每个其他总和中,总是必须正好访问3个元素:前一个总和,即出去的元素(带有-
符号的元素),和那个进入的人(+
)。
-1 -1 11 16 14
-1 -1 17 21 5
-1 -1 20 5 9
-1 -1 -1 -1 -1
-1 -1 -1 -1 -1
第二遍
然后你在第二遍中做了类似的事情(我不打算把它们写出来),你只需要少一些元素。
-1 -1 41 -1 -1
-1 -1 -1 -1 -1
-1 -1 -1 -1 -1
-1 -1 -1 -1 -1
-1 -1 -1 -1 -1
第3步
此步骤与 2x2示例的 1st 和 2nd iteration 完全相同。因此,2x2稀疏rhombs的总和是:
-1 25 15 10 -1
-1 27 18 18 -1
-1 15 24 6 -1
-1 -1 -1 -1 -1
-1 -1 -1 -1 -1
当我们总结第二次迭代的输出时,我们得到:
-1 -1 59 -1 -1
-1 -1 -1 -1 -1
-1 -1 -1 -1 -1
-1 -1 -1 -1 -1
-1 -1 -1 -1 -1
回答只有一个3x3菱形适合矩阵,因此矩阵中只剩下一个元素,这恰好是唯一适合的菱形的总和:59。
答案 1 :(得分:1)
如果问题是关于在菱形'内核'中找到最大的总和,那么是的,有更快的算法。
佩内洛普提出的算法是一个很好的起点 - 然而,当菱形尺寸变大时,所需的进出部分数量增加。这可以通过二维第一次通过来避免,它在两个方向上对角积分值。
[ a b c d] --> integrate a, a+f, a+f+k, a+f+k+p right down
[ e f g h] then integrate the elements in positions c,f,i etc.
[ i j k l]
[ m n o p]
与找到对齐方块的总和相比,这种方法的缺点是必须计算一组单独的对角线,(x + y)是奇数,而(x + y)是偶数;然后结果来自抽样8个积分和而不是4个。
我相信通过从左到右和从上到下整合来最容易理解方法(求和区域)
[1 2 0 3] [1 3 3 6] here every cell contains the summed area
[0 0 1 1] [1 3 4 8] of M[I][J] := sigma i=0..I,j=0..J m[i][j]
[1 0 3 1] --> [2 4 8 13]
[0 1 1 1] [2 5 10 16]
要获得该区域(8..16,100..983),必须只能访问角落元素:
Sigma i=8..16,j=100..983 m[i][j] :== M[7][99]+M[16][983]-M[7][983]-M[16][99]
当要整合的形状旋转45度时,我们必须计算两组积分。如果这是一个棋盘,分别用于白色和黑色方块。然后,每个菱形将由来自一个矩阵M_odd的N * N大小的求和区域和来自另一个求和区域矩阵M_even的(N-1)*(N-1)大小的求和区域组成(反之亦然)。这可以扩展到任何菱形尺寸,具有相同的复杂性。 (并且当N = 1或N = 2时,可以优化从矩阵m中加入元素,并且对于正方形N> 2使用矩阵M)。
评论:也许这等于佩内洛普的建议,但是,我无法弄明白,因为缺乏从5元素菱形到任意大小的概括。
答案 2 :(得分:-1)
我认为使用flood_fill算法只需一次通过,你可以在其中“绘制”相似的颜色区域,即不可见 - 即清除它们。您总结内容并记录两个轴中每个访问像素位置的直方图。 (您可以保持最小和最大x / y位置的计数)。如果直方图遵循轴[1,3,1],[1,3,5,3,1]中的特定模式,则绘制的区域是菱形,否则再次检查这些像素是没有用的,是吗?
131 13432
1 # 1 #
3 ### 4 ####
1 # <-- is a rhomb 4 ## ##
3 ###
1 # <- isn't