bounty还有7天到期。回答此问题可获得+50声望奖励。greybeard想要引起更多关注这个问题:n.m.暗示了Kadane算法的一个应用,我不明白(从什么是数组y
开始?).不寻找一个详细说明的解决方案((去)破坏完整的解决方案欢迎),但对于如何运行在显着更少的时间比O((nm)²)提示-或证明下限Ω((nm)²).锁定10小时.此问题的评论已被禁用,但仍在接受新的答案和其他交互。Learn more。
我目前正在学习和实践this document的试错法,在那里我偶然发现了这个问题:
给定一个由 m 行和 n 列组成的整数网格。找出边与网格的边平行的矩形(每条边的长度大于1),并且位于其边界上的数字之和最大。
- 输入:
第一行包含两个整数 m 和 n。
下一个 m 行:每一行包含描述网格的一行的N个整数。
- 输出:
我们发现的最大金额。
- 制约因素:
2 <= m,n <= 500
运行时间< 3秒
例如:
输入:
5 4
9 -2 -1 3
-10 -5 1 -4
1 -1 2 -2
3 0 0 -1
2 2 -1 2
输出:
8
说明:
在这里,位于其边界上的数字之和最大的矩形是:
1-12
3 0 0
22比1
其和为1 + -1 +2 +0 + -1 +2 +2 +3 = 8
尝试利用最大和矩形的第三方坚韧输入:
5 5
0 1 0 1 0
0 0 -1 0 0
0 0 0 0 0
0 0 -4 0 0
0 1 0 2 0
我尝试创建数组的前缀和p[m][n]
,可以计算右下角位置为(i
,j
),矩形的宽度和高度为(w
,h
)的矩形的边界和:
sum = (p[i][j] - p[i][j-w] - p[i-h][j] + p[i-h][j-w])
- (p[i-1][j-1] - p[i][j-w+1] - p[i-h+1][j] + p[i-h+1][j-w+1])
这里,(p[i][j] - p[i][j-w] - p[i-h][j] + p[i-h][j-w])
计算矩形的所有整数的和,(p[i-1][j-1]—p[i][j-w+1] - p[i-h+1][j] + p[i-h+1][j-w+1])
计算矩形的内部和(不包括边界)。
我必须使用四个嵌套的 for 循环来找到i
、j
、w
和h
的所有可能值,并相应地更新最大和,这给了我一个超过时间限制(TLE)的限制,因为限制是 * 运行时间小于1秒 *。
正如一个用户所建议的,我创建了一些辅助函数来帮助我计算一个矩形的边框和,该矩形的左上角位置为(x0
,y0
),右下角位置为(x1
,y1
),这帮助我解决了一些问题:
int sum(int x0, int y0, int x1, int y1)
{
if (x0 < x1 && y0 < y1)
{
return p[x1][y1] - p[x0][y1] - p[x1][y0] + p[x0][y0];
}
else if (x0 == x1 && y0 == y1)
{
return a[x0][y0];
}
else
{
return 0;
}
}
int border(int x0, int y0, int x1, int y1)
{
return sum(x0, y0, x1, y1) - sum(x0+1, y0+1, x1-1, y1-1);
}
但是,我仍然必须找到x0, y0, x1, y1
的所有可能值,这给了我一个TLE。
时间限制是3秒。
2条答案
按热度按时间6tr1vspr1#
好的,我将此作为一个可能的动态编程解决方案提交。我相信它是O(N3)(或者,严格地说,如果m和n非常不同,则为mn(m+n))。对于一个500 X500的随机矩阵,它需要一秒钟左右(由我的手表)。对于100 x100随机矩阵,它给出了与蛮力相同的结果。
这个想法是构建一个临时的-形式上是B[i][j][w],但如果仔细完成,则只需要存储两个连续行的B[j][w]-其中这表示宽度w结束(右下)在[i][j]的矩形的最佳和。这需要在i,j,w上循环,因此时间复杂度为O(N3)。
从之前的最佳结果中逐行构建,我相信每次只有两个候选项(如果此图没有太大意义,请道歉)
下面的代码测试了Motomotes的示例1和2(可选)以及一个大型随机矩阵。对于测试,还有一个蛮力求解器(但不要费心在大型矩阵上使用它)。注意,如果矩阵的宽度大于深度,那么我先转置它(为了方便)。
相关例程为int bestRectangleSum(vector &M)
Monomotes示例1的输出:
c9x0cxw02#
正如一位用户所建议的,我尝试使用Kadane的算法来找到网格中的最大矩形和以及前缀和,以减去三角形的内部部分。这将时间复杂度降低到了
O(n^3)
,它在m = n = 500
上运行良好