项目欧拉#219

时间:2008-12-06 20:13:01

标签: algorithm math bitstring

我正在尝试做项目欧拉数219,但我没有掌握它。我正在尝试使用Python,根据项目Euler应该能够在一分钟内完成它!这让我觉得他们不可能想要我计算每个单独的位串,因为在Python中它会太慢 - 必须有一个子O(n)算法。

我已经看过一个递归解决方案,它存储了位串可能的前缀,以便它可以快速选择一个新的位串,甚至可以将它们分组考虑。这仅适用于超过10的强制值:

cost(1) = 1
cost(2) = 5
cost(3) = 11
cost(4) = 18
cost(5) = 26
cost(6) = 35
cost(7) = 44
cost(8) = 54
cost(9) = 64
cost(10)= 74
cost(11)= 85
cost(12)= 96

过去这个,我正在努力理解如何减少问题。始终可以创建类似于以下的模式:

1
01
001
0001
00001
00000

但对于7位以上的字符串来说,这不是最佳选择。任何人都可以指导我应该考虑的事情吗?

6 个答案:

答案 0 :(得分:8)

蛮力不是正确的做法。这是其中一个问题,如果你知道某件事情,那并不难,但如果你从未听说过这件事,那实际上是不可能的。那件事是Huffman trees

[编辑]进一步审查后,似乎你无法在具有特定频率的N个节点上构建一个霍夫曼树,因为字符串的成本函数是4 *(#of 1's)+(#of 0's) 。如果cost函数是字符串的长度(或其倍数),那么你可以创建一个Huffman树。

任何无前缀的代码集都可以表示为类似霍夫曼的二叉树,其中每个节点都有0或2个子节点,叶节点代表代码。给定具有N个节点的树,我们可以构造具有N + 1个节点的树,如下所示:

  1. 选择成本最小的叶子节点,其中叶子节点的成本为4 *(从根到叶子的路径上的#的1)+(路径上的0的#)
    • 将2个孩子添加到该节点
  2. 因此,如果节点的代码先前是xxxx,那么我们从代码集中删除该代码(因为它不再是叶子),并添加两个代码xxxx0和xxxx1。

    现在增加了代码集的总成本

    `cost(xxxx0)+ cost(xxxx1) - cost(xxxx)= cost(0)+ cost(1)+ cost(xxxx)= 5 + cost(xxxx)

    因此,mincost(N + 1)<= mincost(N)+ 5 +成本(N的最佳解决方案中最便宜的代码)。我的理论是,不平等应该是平等的,但我还没有能够证明它。对于您列出的所有强制强制的值,此陈述实际上是相等的。

    如果它是平等的,那么要解决问题,你会做的是:

    1. 以空代码集开始,总成本为零
      • 从1到10 9 迭代,执行:
        1. 在代码集中找到最便宜的代码
      • 通过追加0和1
      • 将该代码拆分为两个
      • 将该代码的费用+ 5加到总费用中
    2. 如果您使用priority queue,则应该能够在O(N log N)时间内执行此操作。考虑到10 9 的上限,这可能是可行的,也可能是不可行的。

答案 1 :(得分:1)

Adam:感谢加载链接 - 看起来非常很有希望!在阅读维基百科文章后,我不确定的是如何考虑系数4。我正在努力将Project Euler问题“映射”到算法中。字母表必须长10 ^ 9项,但重量是多少?

困扰我的另一件事是,霍夫曼编码充其量O(n)肯定太慢了,就像我上面提到的那样......

mattiast:我不认为你的复发是有效的(或者我误解了它!)。我对它的解释是:

def cost(n):
    if n == 1: return 1

    m = None
    for k in range(1, n):
        v = cost(k)+cost(n-k)+k+4*(n-k)
        if not m or v < m: m = v

    return m

print(cost(6))

当它应该是35时,它返回的值是41.所有相同的,如果我的值是正确的,那么我找不到ATT的整数序列百科全书中的差异。

答案 2 :(得分:1)

N = 10 ** 9

t = [0]

for x in xrange(N):   m = min(t)   t.remove(M)   t.append(M + 1)   t.append(M + 4)   print sum(t),t

答案 3 :(得分:0)

我如何解决它,计算成本(n)高达n = 1000,然后只是猜测它是如何从那里开始的。如果你看一下连续值的差异,并使用The encyclopedia of integer sequences(和一些想象力),你可以猜出规则。

您可以使用重复Cost(n) = min {Cost(k)+Cost(n-k)+k+4*(n-k) | 0 < k < n}计算带有一种动态编程的小(&lt; = 1000)示例。

答案 4 :(得分:0)

Adam Rosenfield的解决方案看起来非常有效。现在已经很晚了(大约午夜!)所以我会离开它直到凌晨。我在C中有一个高效的优先级队列实现,所以明天我将尝试使用它并找到解决方案。

我将报告算法的成功,但推理对我来说似乎是合理的,并且它与数据密切相关(如上所述)。但是,正如我一直在喃喃自语,必须有一个子O(n)算法! ; - )

答案 5 :(得分:0)

事实证明,O [n * log(n)]不是太慢,但是大致为O(n)的存储器复杂度是。然而,上面提出的算法可以进一步降低到O(n)时间复杂度和低存储器复杂度。要做到这一点,可以使用数组x,其中x [a] =成本a的数值的数量。

所做出的假设给出了10 ^ 9的正确结果,所以我认为它们是正确的。