我有两个自然数的数组{Ai}
和{Bi}
。所有元素的总和是相等的。
我需要将两个数组的每个元素分成三个自然数:
Ai = A1i + A2i + A3i
Bi = B1i + B2i + B3i
这样A1的所有元素的总和等于B1的所有元素的总和,并且对于所有其他对,它们是相同的。
我最初忘记的重要部分:
A1 j ,A2 j ,A3 j 中的每个元素应位于A j / 3-之间2和A j / 3 + 2或至少等于这些数字之一
B1 j ,B2 j ,B3 j 中的每个元素应位于B j / 3-之间2和B j / 3 + 2或至少等于这些数字之一
因此,数组的元素必须分成几乎相等的部分
我寻找一些更优雅的解决方案,而不仅仅是为两个数组计算所有可能的变体。
答案 0 :(得分:1)
我寻找一些更优雅的解决方案,而不仅仅是为两个数组计算所有可能的变体。
应该可以将它们分开,使得A1,A2和A3的总和接近A的三分之一,而B的相同。将所有值精确地设为三分之一很容易,但这不是可能有自然数字。所以我们必须floor
结果(平凡)并在三个数组上统一分配余数(可管理)。
我不知道它是否是唯一的解决方案,但它可以在O(n)
中运行,我的直觉说它会保留你的不变量(虽然我没有证明):
n = 3
for j=0 to n
A[j] = {}
x = 0 // rotating pointer for the next subarray
for i in A
part = floor(A[i] / n)
rest = A[i] % n
for j=0 to n
A[j][i] = part
// distribute the rest over the arrays, and rotate the pointer
for j=0 to rest
A[x][i]++
x++
/* Do the same for B */
也可以在没有除法的情况下制定循环,仅将A [i]的单个单元(1)分布在A [x] [i]上:
n = 3
for j=0 to n
A[j] = {}
for k=0 to |A|
A[j][i] = 0
x = 0 // rotating pointer for the next subarray
for i in A
// distribute the rest over the arrays, and rotate the pointer
for j=0 to A[i]
A[x][i]++
x++
答案 1 :(得分:0)
您应该查看dynamic programming的原则。
在这种情况下,它似乎与某些coin change problems类似。
至于找到A1_i,A2_i,A3_i,你应该递归地进行:
def find_numbers(n, a, arr):
if arr[n] not empty:
return
if n == 0:
arr[n].append(a)
return
if a.size() > 2:
return
t = n
for each element of a:
t -= element
for i = 0 to :
find_numbers(n, append(a, i), arr)
我们使用arr
,因此我们不需要为每个数字计算可能组合的多倍。如果您在一段时间后查看调用树,此函数将返回arr
的组合,而不是再次计算它们。
在您的主要电话中:
arr = []
for each n in A:
find_number(n, [], arr)
for each n in B:
find_number(n, [], arr)
现在你在arr [n]中拥有每个n的所有组合。 我知道这是问题的一个子部分,但是从arr找到每个A_i,B_i的正确组合是非常类似的。 > 阅读我给你的链接非常重要,这样你才能理解背后的基本理论。
答案 2 :(得分:0)
我添加了规定A1,A2和A3必须在不知道B的情况下从A计算,同样地,必须在不知道A的情况下计算B1,B2和B3。
要求每个A1 i ,A2 i ,A3 i 必须在[A i / 3-2,A i / 3 + 2]意味着A1,A2和A3元素的总和必须大约是A的三分之一。规定迫使我们定义这个完全。
我们将按任何顺序构造数组(例如,从元素0到最后一个元素)。在我们这样做时,我们将确保阵列保持接近平衡。
设x是要处理的A的下一个元素。设a为圆(x / 3)。为了考虑x,我们必须向数组A1,A2和A3追加总共3•a + r,其中r是-1,0或+1。
设d为sum(A1) - sum(A)/ 3,其中和是到目前为止处理的元素。最初,d为零,因为没有处理任何元素。根据设计,我们将确保每步的d为-2 / 3,0或+2/3。
将如下所示的三个值分别附加到A1,A2和A3:
最后,A1,A2和A3的总和由A模3的总和唯一确定。 A1的总和是(sum(A3)-2)/ 3,sum(A3)/ 3,或(sum(A3)+2)/ 3,根据A模3的和是否与-1一致,0 ,或分别为+1。
完成演示:
在任何情况下,a-1,a或a + 1都附加到数组中。 a是圆的(x / 3),因此它与x / 3相差小于1,因此a-1,a和a + 1各自与x / 3相差小于2,满足值必须的约束在[A i / 3-2,A i / 3 + 2]。
当B1,B2和B3以与上述A1,A2和A3相同的方式制备时,它们的总和由B3的总和确定。由于A的总和等于B的总和,因此A1,A2和A3的总和分别等于B1,B2和B3的总和。