<p>在担心花色和不同的价值<code>10</code>的牌之前,让我们先弄清楚有多少不同的价值组合导致<code>21</code>。例如,<code>5, 5, 10, 1</code>就是这样一种组合。以下函数接受<code>limit</code>这是目标值,<code>start</code>表示可以拾取的最低值,<code>used</code>是拾取值的列表:</p>
<pre><code>def combinations(limit, start, used):
# Base case
if limit == 0:
return 1
# Start iteration from lowest card to picked so far
# so that we're only going to pick cards 3 & 7 in order 3,7
res = 0
for i in range(start, min(12, limit + 1)):
# Aces are at index 1 no matter if value 11 or 1 is used
index = i if i != 11 else 1
# There are 16 cards with value of 10 (T, J, Q, K) and 4 with every
# other value
available = 16 if index == 10 else 4
if used[index] < available:
# Mark the card used and go through combinations starting from
# current card and limit lowered by the value
used[index] += 1
res += combinations(limit - i, i, used)
used[index] -= 1
return res
print combinations(21, 1, [0] * 11) # 416
</code></pre>
<p>由于我们关注的是不同的卡片组合而不是不同的价值组合,因此应该修改上面的基本情况,以返回可用于生成价值组合的不同卡片组合的数量。幸运的是,这是一个非常简单的任务,<a href="https://en.wikipedia.org/wiki/Binomial_coefficient" rel="nofollow">Binomial coefficient</a>可以用来计算从<code>n</code>项中选择多少个不同的<code>k</code>项组合。在</p>
<p>一旦知道<code>used</code>中每个值的不同卡片组合的数量,它们就可以相互相乘以获得最终结果。例如<code>5, 5, 10, 1</code>值<code>5</code>结果为<code>bcoef(4, 2) == 6</code>,值{<cd1>}到{<cd14>},值{<cd15>}到{<cd16>}。对于所有其他值<code>bcoef(x, 0)</code>结果为<code>1</code>。将这些值相乘得到<code>6 * 16 * 4 == 384</code>,然后返回:</p>
^{2}$