我有NxM矩阵,其中包含大于或等于0的整数元素。
从任何单元格我可以将1转移到另一个单元格(-1到源单元格,+1到目的地)。 使用此操作,我必须使所有行和列的总和相等。问题是如何找到最少量的此类操作来完成我的任务。在处理过程中,细胞可能是阴性的。
例如,
1 1 2 2
1 0 1 1
0 0 1 1
1 1 1 2
答案是3。
P.s。:我试图自己解决这个问题,但只是蛮力解决方案。
答案 0 :(得分:3)
首先,找到每行和每列的预期总和 1 。
rowSum = totalSum / numRows
colSum = totalSum / numCols
然后,遍历行和列并计算以下值:
rowDelta = 0
for each row r
if sum(r) > rowSum
rowDelta += sum(r) - rowSum
colDelta = 0
for each col c
if sum(c) > colSum
colDelta += sum(c) - colSum
平衡所有行和列的最小移动次数为:
minMoves = max(rowDelta, colDelta)
这是有效的,因为您必须从超过rowSum
的行转移到不超过它的行,并从超过colSum
的列转移到不超过它的列。
如果最初rowDelta
低于colDelta
,那么您将达到平衡所有行的阶段,但列仍然没有平衡。在这种情况下,您将继续从单元格转移到同一行中的其他单元格。如果最初colDelta
低于rowDelta
,则同样适用,这就是我们选择它们之间的最大值作为预期结果的原因。
1 如果totalSum
不是numRows
或numCols
的倍数,则问题无法解决。
答案 1 :(得分:2)
让我们考虑一维情况:您有一个数字数组,并且您可以进行单个操作:从数组的一个元素的值中取1并将其添加到其他元素。目标是使所有元素与最小的操作相等。这里的解决方案很简单:你选择随机的“太大的数字”,然后在随机的“太小”数字中加一个。现在让我描述一下这与手头的问题有什么关系。
您可以轻松计算每列和每行所需的总和。这是矩阵中所有元素的总和除以列数或行数。从那时起,您可以计算出哪些行和列需要减少以及哪些 - 增加。看到这里:
1 1 2 2 -2
1 0 1 1 +1
0 0 1 1 +2
1 1 1 2 -1
+1+2-1-2
Expected sum of a row: 4
Expected sum of a column: 4
现在我们生成两个数组:行中的位移数组:-2,+1,+2,-1
和列中的位移数:+1,+2,-1,-2
。对于这两个数组,我们解决了上述简单的任务。很明显,我们无法以比简单任务所需的步骤更少的步骤解决初始问题(否则列或行中的余额不会为0)。
但是,我将证明初始任务可以通过与解决列和行任务所需的最大步骤完全相同的步骤来解决:
更简单的任务中的每一步都会生成两个索引i
和j
:要从中减去的索引和要添加的索引。让我们假设在列任务的一个步骤中我们有索引ci
和cj
,并且在行任务中我们有索引ri
和rj
。然后我们在初始任务中分配此对应关系:从(ci, ri)
取1并将{1}添加到(cj, rj)
。在某些时候,我们将会遇到这样的情况:例如,列任务可能还有更多步骤,而行任务中则没有更多步骤。我们得到ci
和cj
,但我们对ri
和rj
做了什么?我们只选择ri
= rj
,这样我们就不会搞砸行计算。
在这个解决方案中,我利用了允许在矩阵中获得负数的事实。
现在让我们演示:
Solution for columns:
4->1;3->2;4->2
Solution for rows:
1->3;1->3;2->4
Total solution:
(4,1)->(1,3);(3,1)->(2,3);(4,2)->(2,4)
答案 2 :(得分:1)
Supose thar r1
是具有最大总和的行的索引,而r2
是具有最小总和的行。 c1
列,最大总和,c2
列,最小。
您需要重复以下操作:
Matrix[r1][c1] == Matrix[r2][c2]
我们已经完成了!Matrix[r1][c1] -= 1
和Matrix[r2][c2] += 1