【问题标题】:Number Pyramid algorithm: Numbers 1-15 in a pyramid where each number is the difference of the subjacent numbers数字金字塔算法:金字塔中的数字 1-15,其中每个数字是下面数字的差
【发布时间】:2018-04-07 17:27:51
【问题描述】:

首先:抱歉标题太长,但我发现很难用一句话来解释这个问题;)。是的,我也四处搜索(这里和谷歌),找不到一个像样的答案。

所以,问题是这样的:

数字 1-15 将被放入一个金字塔中(由一个数组表示),如下所示:

       1
     2   3
   4   5   6
  7  8   9   10
11 12  13  14  15

...除了不是真的像这样,因为这个金字塔是错误的。

每个数字“a”都应该由它下面的两个数字“b”和“c”定义:a = |b - c|。所以前两行是正确的,因为 |2-3| = 1。但是第三行当然是错误的,因为|4-5| = 1,但在这些数字之上还有 2。一开始,金字塔是空的,任务是寻找填充这个金字塔的算法。

对我来说,这似乎是一个可以使用某种Backtracking 算法解决的问题,尽管我还不确定递归的简单基本情况是什么。

尽管如此,我正在努力帮助我的侄子,在他学校的课堂上,他们还没有听说过任何关于递归的事情——更不用说回溯了。所以我目前正在尝试找到一种方法来解决这个金字塔的问题,使用某种嵌套的 for 循环或其他东西,但老实说......我目前正在碰壁,我想不出一个像样的解决方案。

有人有什么想法吗?

干杯,

/tehK

P.s:哦,我忘了...他们应该使用的语言是 C#(金字塔应该是一个数组),但我也可以处理任何其他语言,伪代码或你有的。这与编码无关,而与算法有关。

【问题讨论】:

    标签: algorithm numbers backtracking


    【解决方案1】:

    底行有 15*14*13*12*11=360360 种可能性。一旦你有底行,金字塔的其余部分就确定了。所以简单地检查每一种可能性,看看它是否不包含重复的数字。可以通过回溯来优化这一点,但您要求不回溯。

    下面是示例代码:

    import itertools
    
    def pyramid():
        for b in itertools.combinations(range(1, 16), 5):
            for xs in itertools.permutations(b):
                rows = [xs]
                while len(rows[-1]) != 1:
                    rows.append(tuple(abs(a-b) for a, b in zip(rows[-1], rows[-1][1:])))
                used = sum(rows, ())
                if all(1 <= i <= 15 for i in used) and len(set(used)) == 15:
                    yield rows
    
    for p in pyramid():
        for row in p[::-1]:
            print ' ' * 2*(5-len(row)) + '  '.join('% 2d' % n for n in row)
        print
    

    输出:

             5
           4   9
         7   11   2
       8   1   12   10
     6   14   15   3   13
    
             5
           9   4
         2   11   7
       10   12   1   8
     13   3   15   14   6
    

    找到的两个解决方案本质上是相同的(一个是另一个的镜像)。

    【讨论】:

    • 14*13*12*11*10 组合为(按逻辑),15 必须在底行。
    • 非常感谢您的回答。我想过这样的事情,但由于在这个解决方案中,你基本上仍然只是在底行尝试超过 300000 个排列,这有点像作弊;)也就是说,考虑到回溯需要的所有递归,这绝对是我最喜欢的那个。作为一个不习惯每天看到 Python 的人,我很惊讶它的简洁性;)我明天将在 C# 中实现它(不幸的是没有 itertools),看看它是如何进行的!跨度>
    【解决方案2】:

    小线索:
    底行定义了所有金字塔,并且该行只有15!/10! 变体(如果我们省略反射,实际上只有一半)。

    因此,遍历所有可能的排列并检查有效的金字塔是否可能并不是很困难

    【讨论】:

    • !14/9!,因为 15 必须在底行。
    猜你喜欢
    • 1970-01-01
    • 2012-08-29
    • 1970-01-01
    • 1970-01-01
    • 2015-07-01
    • 1970-01-01
    • 2019-07-19
    • 1970-01-01
    • 2023-01-08
    相关资源
    最近更新 更多