这实际上是一个基于麻将的问题,但是基于Romme或什至基于扑克的背景也很容易理解。
在麻将中,将14张磁贴(瓷砖就像扑克中的纸牌一样)排列成4套和一对。街道(“ 123”)始终只使用3个图块,数量不多也不少。一组相同的集合(“ 111”)也恰好由3个图块组成。这导致3 * 4 + 2 = 14个图块的总和。
这里有许多与“坎”或“十三孤儿”无关的例外。颜色和值范围(1-9)对算法也不重要。
我正在尝试确定是否可以按照上述方式布置一只手。由于某些原因,它不仅应该能够处理14个而且可以处理任意数量的瓷砖。(下一步将是找出需要交换多少张方砖才能完成一手操作。)
例子:
11122233344455-足够简单,4套和一对。 12345555678999- 123,456,789,555,99 11223378888999- 123,123,789,888,99 11223344556789-不是一个有效的手
11122233344455
12345555678999
11223378888999
11223344556789
我目前尚未实现的想法是:对于每个磁贴,尝试使a)一条街道b)一组c)一对。如果没有一个有效(或者会有一对以上),请返回上一个迭代并尝试下一个选项,或者,如果这是最高级别,则失败。否则,从剩余图块列表中删除使用过的图块,然后继续下一个迭代。
我相信这种方法行之有效,并且也将相当快(性能是“不错的奖励”),但是我对您对此的观点感兴趣。您能想到其他解决方案吗?这个或类似的东西已经存在吗?
(不是功课,我正在学习打麻将。)
街道和集合中的值之和可以除以3:
因此,如果将所有数字加到一个已求解的手中,则将得到3N + 2M形式的数字,其中M是该对中磁贴的值。total % 3对于M的每个值,除以三()的余数为:
total % 3
total % 3 = 0 -> M = {3,6,9} total % 3 = 1 -> M = {2,5,8} total % 3 = 2 -> M = {1,4,7}
因此,不必测试九对可能的对,您只需要根据一个简单的加法尝试三对。对于每个可能的对,删除具有该值的两个图块,然后继续进行算法的下一步以确定是否可能。
一旦有了这个,就从最低的值开始。如果该值少于3个图块,则表示它们必定是一条街的第一个元素,因此请删除该条街(如果不能,则因为缺少n + 1或n + 2图块,则表示该手无效),然后移至下一个最小值。
如果至少有三个具有最低值的图块,请将它们作为一个集合删除(如果您询问“它们是否是街道的一部分?”,请考虑是否存在),那么还有三个图块n + 1和三个n + 2的像素数,也可以将其转换为集合)并继续。
如果您的手空了,则该手有效。
例如,对于您的无效手牌,总数为60,这意味着M = {3,6,9}:
Remove the 3: 112244556789 - Start with 1: there are less than three, so remove a street -> impossible: 123 needs a 3 Remove the 6: impossible, there is only one Remove the 9: impossible, there is only one
在第二个示例中12345555678999,总数为78,这意味着M = {3,6,9}:
Remove the 3: impossible, there is only one Remove the 6: impossible, there is only one Remove the 9: 123455556789 - Start with 1: there is only one, so remove a street -> 455556789 - Start with 4: there is only one, so remove a street -> 555789 - Start with 5: there are three, so remove a set -> 789 - Start with 7: there is only one, so remove a street -> empty : hand is valid, removals were [99] [123] [456] [555] [789]
您的第三个示例11223378888999也共有78个,这会导致回溯:
Remove the 3: 11227888899 - Start with 1: there are less than three, so remove a street -> impossible: 123 needs a 3 Remove the 6: impossible, there are none Remove the 9: 112233788889 - Start with 1: there are less than three, so remove streets -> 788889 - Start with 7: there is only one, so remove a street -> 888 - Start with 8: there are three, so remove a set -> empty, hand is valid, removals were : [99] [123] [123] [789] [888]