如何有效地为8球比赛提供台球?

时间:2013-01-23 22:31:28

标签: algorithm optimization language-agnostic

由于8球比赛的台球可以在多种规则下进行,所以这就是我所说的货架:

enter image description here

即。 8球必须在中心,并且沿着两侧,条纹和固体必须交替。剩下的两个球(条纹和实心)并不重要。

假设你刚刚完成一个游戏,收集球,将它们放入机架并继续安排它们开始一个新的。他们现在是随机的。你怎么办?

免责声明:绘画艺术如下

enter image description here

一种简单的方法是按顺序开始,top - >底部和左侧 - >右。

例如,我们假设1处于正确的位置。 5不是2,我们将其与4交换,然后我们将38(或与4)交换,但这已经效率低下,因为我们'要么将8移动到中心,要么将4移到{{1}}的位置 - 即不是最后的位置。

我们还决定在角落里制作哪种类型的球。你是如何预先决定的?你应该考虑到已有多少球?在我的例子中,如果你想要角落里的灰色,你已经有3个(球1,10,14)。如果你想要角落里的白色,你只有2个(2,11)。这有关系吗?

为了形式化,我们可以假设我们可以做两个三个操作:

  • 交换两个相邻的球
  • 交换两个不相邻的球
  • 旋转架子

由于我们可以使用双手,让我们假设我们可以并行第一次操作(同时交换2对球),而我们一次只能交换两个不相邻的球。

哪种方法最适合此任务,最大限度地缩短时间(以所描述的时间单位)?贪婪是最好的吗? (这就是当我把它们架起来的时候我是这么做的),我猜)

编辑:根据现有(或以前的答案) - 你可能会认为角落里的条纹比条纹更多意味着大步更喜欢角落 - 不是说它不是真的,但如果你做出这个假设,请证明它

5 个答案:

答案 0 :(得分:5)

请注意!这个答案是在轮换要求之前写的。请谨慎行事:)

这是我对问题的初步看法。

要做的第一件事是计算外部的奇偶校验 - 如果它适合'角落中的条纹'则为+1,如果它适合'角落中的实体'则为-1,如果是8球则为+0。这给了我们从+12到-12的范围,我们的目标是我们更接近的极端。 (如果+0,选择+12或随机)

例如,这是+1 +1 +1 -1 -1 +1 -1 -1 -1 +1 +0 -1因此它在角落里是-1倾斜实体:

x o x x o
 x o x o
  8 x o
   o x
    o

接下来要做的就是将8球移到中心位置。 如果你可以做两个相邻的交换,将两个球移动到位,而不是一个相邻的交换,只将一个球移动到位(或者如果它在一个角落中,则单个非相邻),这样做。 / em>的

x o x x o
 x 8 x o
  o x o
   o x
    o

在我们移动8球之后,两个相邻交换球的所有组合共用球可以由相邻的交换产生相同的,所以我们必须立即考虑复杂性。

按此优先顺序排列所有剩余的动作:

- 外面两个相邻球之间的交换是“值4”(如果它是我们的最后一个,则为2)

- 两个相邻球之间的交换,一个在外面,是'值2'(如果它是我们的最后一个)

- 外面两个球之间的交换是“值2”

- 两个球之间的交换,一个在外面,是'值1'

从上到下执行它们。

所以我们移动顶部的左侧,左侧(4),右侧的o(2),左侧的o(2),然后将x顶部与中间的o交换(2)。我们最终在2-2-1系列中进行了五次交换,因此有三次移动。

o x o x o
 x 8 x x
  o o o
   x x
    o

(值得注意的是,如果我们针对角落中的条纹,这个问题就会得到解决。)

x x o o x
 o 8 o x
  o x o
   x o
    x

我认为要求4回合是不可能的,但我还没有证明这一点。

另一个有效的例子:

这个奇偶校验为+1,所以我们的目标是角落里的条纹:

8 o o o x
 o o o x
  o x x
   x x
    x

与中心x交换8球 (1 - )

x o o o x
 o o o x
  o 8 x
   x x
    x

交换两个相邻的外部,4个点 (1-1)

x o o o x
 o o o x
  x 8 x
   o x
    x

将相邻边缘交换到中心,2点 (1-2 - )

x o o o x
 o o x o
  x 8 x
   o x
    x

交换边缘到边缘,2点 (1-2-1 - )

x o x o x
 o o x o
  x 8 x
   o o
    x

3招。

编辑:这对于开幕式中的示例非常有效,通过两个步骤解决它:

这个奇偶校验为+1,所以我们的目标是角落里的条纹:

x x o o x
 o o x o
  o o 8
   x x
    x

在边缘上用x交换8,然后用o在中心(求解两条边) (2 - )

x x o o x
 o o x o
  o 8 x
   x o
    x

在左上角和左下角交换相邻的o和x(求解四条边) (2-2 - )

x o x o x
 o o x o
  x 8 x
   o o
    x

2招。

答案 1 :(得分:4)

你有两个八球,骗子。

在给定的示例中,解决方案需要2个步骤:

2-5,3-8
3-4,11-12

通过为dynamic programming(DP)配置问题,可以获得最佳解决方案。由于问题是多阶段的,固定成本且没有不确定性,因此将存在最佳解决问题的DP矩阵。

创建矩阵:请注意,考虑对称性,8球可以位于9个位置之一。固体可以以约(14选7)/ 2 = 1716种不同方式排列。这意味着机架配置的总数约为1716 * 9 = 15,444。因此,您有15,444种不同的可能状态。计算从这些状态中的任何一个到任何其他状态的成本。这导致具有15,444 * 15,444个细胞的基质,或约25亿个细胞。识别所有终端状态单元。要解决矩阵问题,您需要从起始状态开始向前搜索,直到达到结束状态(或直到达到高于当前最低成本的成本总额)。通过这样做,您可以证明找到了所有成本最低的路径。

请注意,上述解决方案有点幼稚,可以通过各种方式进行优化,以产生更小的矩阵。例如,您可以使用旋转对称来减少单元格数量,并将成本增加1(用于旋转机架)到正确的路径,除了将8球放在其中一个低中心位置。

Pseudocode:

Create DP Matrix:

(1) determine number of possible arrangements, A, of balls
(2) for each arrangement, make a list of possible unique moves  
---- the possible moves are:  
------- rotating right  
------- rotating left  
------- exchanging any pair of balls  
------- exchanging any two pairs of adjacent balls  
(3) for each move in A store a pointer to the resulting arrangement  
(4) for each arrangment make an attribute indicating whether it is an end state  

Solve Problem  
(5) goto arrangement for starting position S  
(6) set best-cost-so-far (BCSF) variable to infinity
(6) breadth search from S, accumulating current cost CC as +1 for each transition
(7) if you reach an end state CC < BCSF, then set BCSF = CC and make solution list contain only the current path
(8) if you reach an end state CC = BCSF, then add path to solution list
(9) if CC > BCSF abandon branch and try next branch

The result will be a list of all possible solutions and the minimum cost BCSF.

答案 2 :(得分:4)

15!/(7!7!1!)=51480个可能的职位。其中,4个是最终的:可以更换球8和9,并且可以反转条纹/固体。我们会说这些位置在距离0处。

对于这4个位置中的每一个,生成所有可能的移动(1个交换或2个相邻交换)。对于之前未见过的这些移动所产生的每个位置,记住用于生成它的移动,并将这些位置给予距离1.然后对距离1处的每个位置执行相同的操作,并给出新位置距离2.保持这样做直到没有新的职位。

这利用了这样一个事实:正如@DPenner指出的那样,旋转总是可以用相邻的移动来代替。

由于掉期是他们自己的反转,从A位移到B的移动也是将位置B移回A的移动。

所以,你最终会得到一个所有位置的列表,对于每个不是最终位置的位置,这一移动肯定会使它更接近最终位置。

你会发现有232个位置需要至少4次移动。 (编辑:我的邻接表之前包含错误。)例如:

      6-9,14-15     2-12       2-5,4-7       1-2
    x           x           x           x           o
   x x         x x         8 x         o x         x x
  x o x   =>  x o o   =>  x o o   =>  o 8 o   =>  o 8 o
 o o o x     o o x x     o o x x     x o x x     x o x x
o 8 o o x   o 8 o x o   o x o x o   o x o x o   o x o x o

没有初始位置需要超过4次动作。

编辑:首先交换8球的策略不是最佳的。例如:

         5-11     12-13,14-15    4-7,6-10
    x            x            x            x
   o o          o o          o o          o o
  o x o   =>   o 8 o   =>   o 8 o   =>   x 8 x
 x o x x      x o x x      x o x x      o o x o
8 x o x o    x x o x o    x o x o x    x o x o x

但我们可以做得更好:

         3-11       1-2,3-5
    x            x            o
   o o          o 8          x x
  o x o   =>   o x o   =>   o 8 o
 x o x x      x o x x      x o x x
8 x o x o    o x o x o    o x o x o

问题在于x是角落的错误类型,所以我们失去了一个动作。

相反,策略应该是寻找一个不合适的球,但不能与相邻的球交换,要么是因为它们是相同类型的,要么它们已经处于适当位置。角落应该是首选,因为它们具有最少的相邻交换选项。它应与位置正确的球交换。如果第一球的最终位置的球是错误的,则应选择错误位置的相邻球。这样,随后的相邻交换将把这些球放在正确的最终位置。

在上面(计数器)示例中,8球需要长时间交换才能到达其最终位置。但是,#5中的x是错误的类型,所以我们交换相邻的o,第二行中的第二个。

前面有4个动作的例子解决如下:

        11-2         12-5        13-3       9-10
    x           x           x           x           x
   x x         o x         o x         o o         o o
  x o x   =>  x o x   =>  x 8 x   =>  x 8 x   =>  x 8 x
 o o o x     o o o x     o o o x     o o o x     o o x o
o 8 o o x   x 8 o o x   x o o o x   x o x o x   x o x o x

在第一步中,我们选择左下角的o。第一个x位于第二位。然后我们在#12选择8,我们可以带回#5。下排中间的o是下一个。我们将它与下一个错误放置的x在#3交换。最后,我们交换#9和#10来获得最终的机架。路径与以前不同,但我们仍然以4个动作完成。

编辑:还有一点:在进行相邻交换时,应优先考虑那些最终未将两个球放在最终位置的交换。原因是这意味着总共需要至少两次移动,因此最好尽快进行第一次移动。

例如,问题中的机架可以通过两个动作解决:(2-4),(5,6)和(3-6),(12-13)。 8球首先被移动到最终位置,即使它被交换的白球尚未处于最终位置。如果首先完成两个周边交换(2-4),(12-13),你仍然需要两个动作才能到达最终的机架,总共进行次优的3次移动。

答案 3 :(得分:3)

这一直是一个充满挑战,令人沮丧和有趣的问题。我猜想以下是最佳解决方案:

  • 根据Patashu的奇偶校验方法选择条纹或实体是否在角落
  • 无轮换
  • 每次测量时,除了+3移动可以将8球放在中心位置之外,进行最高得分的移动
  • 如果是领带,选择无关紧要? 修改:请参阅底部的注释。关系很困难。

(我根据正确位置球的净差异得分移动。)

以下是两个示例机架:

    x            8
   x x          o o
  o o x        o o x
 o o x x      o x x x
8 o o o x    o x x o x

如果我们将位置1到15从左到右,然后从上到下,第一个机架编号 解决方法为(2-4 / 3-5)(5-11)(10-13),第二个机架解为(4-8 / 11-12)(5-10)(1-5)。

我最近的一次证明尝试中有一部分只在11个不同的机架上失败,直到对称(上面显示的两个是失败的变体)。以下是我在尝试中发现的两个引理,希望能帮助其他人提供证据。

引理1:不需要旋转

请注意,如果我们需要在解决方案的某个时刻进行轮换,那么何时(旋转不会更改任何可用的交换)并不重要。此外,我们只需要最多一次旋转,因为顺时针旋转2次=逆时针旋转1次,反之亦然。

因此,如果需要,我们可以选择在最后一步中进行旋转。此时,由于外部的旋转对称性,外部必须是正确的。因此,8球将位于三个中心球之一。如果它在正确的位置,我们不需要轮换。否则,我们可以使用它,但注意交换也可以完成机架。因此,在最佳解决方案中没有必要。

引理2:贪婪是最佳的,如果它在3次移动中解决了架子

让策略A成为贪婪的解决方案,策略B是任何试图加快速度的非贪婪解决方案。 B必须至少进行一次非贪婪行动。必要时,这不是最后的举动。因此,如果A需要n次才能完成一个机架,B必须在n-2或更早的时候进行非贪婪的移动。这意味着,如果A在2圈或更少的时间内解决了机架,那么它是最佳的。


编辑:好吧,我只是在程序化测试中运行我的算法,发现它甚至不一致。事实上,似乎很难打破关系。考虑以下机架:

    x
   o o
  x o x
 x 8 o x
x o o x o

我的算法将执行以下移动序列之一:(5-8 / 13-14)(7-8 / 10-15),(5-8 / 10-15)(7-8 / 13-14) ),(5-8 / 14-15)(10-13)(7-8),(5-8 / 14-15)(7-8)(10-13),(5-8 / 9-10) )(14-15)(7-13),(5-8 / 9-10)(7-13)(14-15),(5-8 / 9-10)(13-14)(7-15) ),或(5-8 / 9-10)(7-15)(13-14)。前两个在最优的2个时间测量中解决了它,但其他的在3个时间测量中解决了它。问题是(14-15)和(9-10)开关破坏了第二圈可能的+4移动。对该算法的修改可能需要预见,然后快速复杂化。我开始认为没有“简单”的解决方案,@ JeffreySax的解决方案就是要走的路。还要注意,这个机架也挫败了贪婪的解决方案。贪婪的解决方案可以做(13-14 / 10-15)(5-8)(7-8)或(13-14 / 10-15)(7-8)(5-8)。

答案 4 :(得分:3)

萨卢特,首先我必须说这是一个非常有趣和有趣的问题,而且我在没有想到什么时候进行了比赛,尽管总共15个球,一些额外的动作并不重要。

根据货架描述和图片,我们得到以下规则

  1. 角落总是相同类型
  2. 每边的中间总是与角落相同的类型
  3. 接触角落的每组2个球总是相同的类型(与角相反的类型)
  4. 内三角一直是8ball,条纹和实心(8球在上面)
  5. 在两侧,彼此靠近的球将始终交替类型
  6. 正如@ Lemma 1中所说的那样,旋转是不必要的,因为它们可以用交换代替,只要成本相同。如果你是拉比克的粉丝,并选择使用它们,你只需要一个。

    在少于4次交换中无法解决! (总是

    你的示例图像最好证明这一点,无论你计算它是什么,你需要从他们的位置移除6个颜色球和8ball =&gt;这是3½交换,因为交换需要2个球,让我们将其转换为4个交换 这是为什么? 因为它不符合所有规则:

    • [5,1,4] [2,6] [11,13] [10,12]不能彼此靠近(休息5)
    • 8ball位于一边而不是中间三角形(中断4)
    • [5,4] [6,12] [13,9]不是同一类型(中断3),而且在[1,5,4]的情况下,该集合与角落不对(中断3)再次)
    • [2][11]与角落的类型不同(中断2)

    算法

    8ball spots
    第一步:修复8球
    将8ball交换到它的位置。无论如何它都需要在那里 这是旋转的唯一机会(如果8ball在内三角形中开始,但位置不正确)

    Count红色位置相同类型的球最多 最高数量的球停留,其余的点必须换掉。

    IF count is 3 {
        #inside triangle will choose 
        IF inside triangle has 2 of a kind, that type stays (in the red spots)
        ELSE pick random
    }
    

    开始交换:

    • 做角落(挑选一个需要改变的球并在角落找到相反的球)
    • 做中段(挑选一个需要改变的球,在一个中间找到一个相反的球)
    • 如果完成了角落和中间,则最后一次交换位于内三角

    示例演示:

    swap 8 with 3  #move1
    count[stripe]=3 [6,13,9]  
    count[solid]=3 [5,4,12]
    highest count=3, checking inside, inside is correct, random pick: stripes stay
    Pick 5, corners() correct, swap with middles(2)  #move2
    Pick 4, corners() correct, swap with middles(11)  #move3
    Pick 12, corners() correct, swap with middles(3)  #move4
    Done.
    

    如果随机选择会选择固体保留:

    Pick 6, swap with corners(10)  #move2
    Pick 13, swap with corners(1)  #move3
    Pick 9, swap with corners(14)  #move4
    Done.
    

    DEMO2:

    用7改为3,用第15号球取代'白球8号' demo2_with_ball_15

    swap 8 with 3  #move1
    count[stripe]=3 [6,13,9]  
    count[solid]=3 [5,4,12]
    highest count=3, checking inside, inside has 2 of a kind(stripes) => stripes stay
    Pick 5, corners() correct, swap with middles(2)  #move2
    Pick 4, corners() correct, swap with middles(11)  #move3
    Pick 12, corners() correct, swap with middles(15)  #move4
    Done.
    

    Have fun!

    PS:您可能还希望算法变体#2 counts灰色位置,但我发现现实场景更容易使用红点。