我正在处理一个HackerRank问题,该问题是在反转行和列之后找到2N x 2N矩阵的左上象限中元素的最大总和。例如,如果矩阵是
M = [
112 42 83 119
56 125 56 49
15 78 101 43
62 98 114 108
];
然后在获得矩阵后,可以通过反转行和列形成的最大总和为119 + 114 + 56 + 125 = 414
M' = [
119 114 42 112
56 125 101 49
15 78 56 43
62 98 83 108
];
从反转第2列然后第0行。
我还没有找到一个简单的解决方案,但我提出了一些可能有用的事实:
NxN
求和。 M[0,1]=42
可以替换为M[0,2]=83
或M[3,2]=114
或M[3,1]=98
),因为您还必须考虑在此过程中拖动的其他元素。 除了这些事实,我想不出有什么能帮助我构建一个简单的解决方案。我有什么明显的事实吗?昨晚我熬夜思考这个问题。 :)
答案 0 :(得分:1)
让我们开始观察元素(N - 1, N - 1)
只能位于(0, 0)
,(N - 1, 0)
或(0, N - 1)
位置的事实。
考虑一个(r, c)
元素。可以观察到它只能处于以下四个位置之一:(r, c), (N - r - 1, c), (r, N - c - 1)
或(N - 1 - r, N - 1 - c)
可以证明总是有一系列操作将位于上述矩形顶点的四个数字中最大的一个放在左上象限而不改变其余部分(以证明它) ,人们可以只考虑所有情况并提供一个明确的构造来完成它。它很长但很简单,所以我不会在这里发布。)
这两个观察结果给出了以下解决方案:
int sum = 0;
for (int i = 0; i < n / 2; i++)
for (int j = 0; j < n / 2; j++)
sum += max(a[i][j], a[i][n - j - 1], a[n - i - 1][j], a[n - i - 1][n - j - 1]);
答案 1 :(得分:1)
如果不考虑捷径,总是可以委派。不仅是stackoverflow用户,还有CPU。即蛮力搜索。
蛮力适用于这个小矩阵 - 假设深度为4已经绰绰有余,并且树的分支因子是let data =
let values =
[|
112; 42 ; 83; 119;
56 ; 125; 56; 49;
15 ; 78 ; 101; 43;
62 ; 98 ; 114; 108
|]
Array2D.init 4 4 (fun r c -> values.[4 * r + c])
let upperQuadrantSum (m : int[,]) =
[ for r in 0..1 do for c in 0..1 do yield (r,c) ]
|> List.sumBy (fun (r,c) -> m.[r,c])
let reverseRow row (m : int[,]) =
Array2D.init 4 4 (fun r c -> if r = row then m.[r,3-c] else m.[r,c])
let reverseCol col (m : int[,]) =
Array2D.init 4 4 (fun r c -> if c = col then m.[3-r,c] else m.[r,c])
let possibleActions =
[ reverseRow 0; reverseRow 1; reverseRow 2; reverseRow 3;
reverseCol 0; reverseCol 1; reverseCol 2; reverseCol 3;
]
let maximize metric maxDepth m0 =
let rec search depth m =
let value = metric m
if depth = maxDepth
then value
else
possibleActions
|> List.map (fun a -> let m1 = a m in max (metric m1) (search (depth+1) m1))
|> List.max
|> fun msearch -> max value msearch
search 0 m0
let solve = maximize upperQuadrantSum
,其中N分别是数字或行和列。 (N行可以反转,N列。)
这里,对于问题中的4x4矩阵,各自的解决方案:
let inline solve1 m =
let n = Array2D.length1 m
let candidates r c =
[ r,c ; n-1-r,c ; r,n-1-c ; n-1-r,n-1-c ]
[
for r in 0..n/2-1 do
for c in 0..n/2-1 do
yield (candidates r c |> List.map (fun (r,c) -> m.[r,c]) |> List.max)
] |> List.sum
solve1 data
在fsi中,发出:
解决7个数据;;
val it:int = 414
当然,正如其他答案所述,一旦想到优化, 很高兴有蛮力解决方案,以验证两者产生 同样的结果:
#include "opencv2/opencv.hpp"
很抱歉没有用C#编写代码,但.fsx文件和fsi比创建另一个C#应用程序容易得多......