我正在开发一款使用拉姆风格三张牌的纸牌游戏。从随机选择的卡片中,我需要算法来挑选哪些卡片能够获得最高数量的卡片。
通过“拉米式三件套”我的意思是:
例如,给出卡片:6D,7D,7C,7H,8D,8C,9C,10H
我可以形成一套:{7D,7C,7H},但这将是我唯一能摆脱它的一套,而且不是最佳的。
在这种情况下,最佳集合为:{{6D,7D,8D},{7C,8C,9C}}
我尝试过蛮力(通过所有给定的牌进行置换,看看在排列中按顺序排列的是什么),但事实证明这种情况太慢了。这个问题感觉它与其他已解决的问题有相似之处,这就是我在这里问的原因。
答案 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提到的用于解决此问题的回溯算法。