找到最佳数量的拉米式集合的算法?

时间:2009-02-12 17:40:18

标签: algorithm

我正在开发一款使用拉姆风格三张牌的纸牌游戏。从随机选择的卡片中,我需要算法来挑选哪些卡片能够获得最高数量的卡片。

通过“拉米式三件套”我的意思是:

  • 所有三张牌都有相同的价值,就像三个杰克一样。 OR
  • 所有三张牌都是相同的套装并按顺序依次排列,如7,8,9所有钻石。

例如,给出卡片:6D,7D,7C,7H,8D,8C,9C,10H
我可以形成一套:{7D,7C,7H},但这将是我唯一能摆脱它的一套,而且不是最佳的。
在这种情况下,最佳集合为:{{6D,7D,8D},{7C,8C,9C}}

我尝试过蛮力(通过所有给定的牌进行置换,看看在排列中按顺序排列的是什么),但事实证明这种情况太慢了。这个问题感觉它与其他已解决的问题有相似之处,这就是我在这里问的原因。

3 个答案:

答案 0 :(得分:5)

如果你有N张牌(N = 8),你可以按时间N *(N - 1)*(N - 2)枚举所有不同的三元组(N = 8,你得到336)。这很快。检查哪些三元组是“拉米风格”集合,并将它们作为整数三元组存储在表格中(整数表示卡片的序列号)。

这是第一步。第二步是进行组合优化并计算最佳选择。这样做的简单方法是使用回溯搜索。您在找到的三元组上运行索引('i')。首先,您尝试在解决方案中包含'i'th三元组,然后递归地从索引i + 1继续;然后你回溯并决定解决方案中的'i'th triple not ,并递归地从i + 1继续。对此有很多优化,但对于小集合,它可以很好地工作。

以下是如何使用您的示例:

卡片:6D,7D,7C,7H,8D,8C,9C,10H

让我们列举所有可能的三元组:

Cards        Index triple
6D 7D 8D     <0, 1, 4>
7D 7C 7H     <1, 2, 3>
7C 8C 9C     <2, 5, 6>

完整的回溯搜索是这样的:

Decide on <0, 1, 4>:
  <0, 1, 4> INCLUDED:
     <1, 2, 3> CLASHES with <0, 1, 4>
     Decide on <2, 5, 6>:
       <2, 5, 6> INCLUDED:
          Solution with 2 sets (* BEST SOLUTION)
       <2, 5, 6> EXCLUDED:
          Solution with 1 sets
  <0, 1, 4> EXCLUDED:
     Decide on <1, 2, 3>:
        <1, 2, 3> INCLUDED:
           <2, 5, 6> CLASHES with <1, 2, 3>
           Solution with 1 sets
        <1, 2, 3> EXCLUDED:
           Decide on <2, 5, 6>:
             <2, 5, 6> INCLUDED:
                Solution with 1 set
             <2, 5, 6> EXCLUDED:
                Solution with 0 sets

然后你选择大多数套装的解决方案(用星号标记)。

这很容易实现。试试吧!

答案 1 :(得分:1)

我的直觉方法是首先发现所有可能的套装,检查每张卡片,然后搜索可以用该卡片制作套装的内容(即连续的东西和相同价值的东西。)一旦你得到所有的东西。可能的设置,这应该是一个非常快速的操作,除非你有非常大量的卡,然后你可以制作一个集合的地图排除包含其他集(他们使用相同的卡)。此时,甚至置换集合的所有合法组合(对于我没有的每个集合;如果我可以在我当前的集合中合法使用它,请尝试添加它;重复)应该足够快以便服务。

答案 2 :(得分:1)

要查找所有可能的有效三元组,您可以执行两个步骤:

1. sort cards first ascending by number, then by suit, as you did
   in your example and look what triples you can get
2. now sort a second time, but first by suit and then by number 
   and look what triples you can get

In step 1) you can just look sequencially for 3 same numbers => O(n)
In step 2) the same, but now looking for 3 sequential numbers of the same suit. => O(n)

合并这两个结果可以为您提供所有可能的三元组。如果我没错,那么你就达到了maximum set packing的NP难问题,因为你想获得非重叠三元组的最大子集。由于卡的数量有限且不是很高,您可以使用例如antti.huima提到的用于解决此问题的回溯算法。