52张卡牌(52 * 51 * 50 / 3! = 22100)
中有3张牌的22100种组合。
以下是所有这些组合的枚举:
static const ins cards_count = 52;
int boardId = 0;
for (int b1 = 0; b1 < card_count; b1++)
{
for (int b2 = b1 + 1; b2 < card_count; b2++)
{
for (int b3 = b2 + 1; b3 < card_count; b3++)
{
cout << boardId << endl;
boardId++;
}
}
}
是否可以编写将b1,b2,b3转换为boardId(不使用地图)的索引器功能?如果这很难,你可以建议一些将b1,b2,b3映射到int size hash的散列函数。
答案 0 :(得分:3)
有。它也很简单,我简单地想过写下怎么做,但后来我发现我需要很多数学符号。
这个想法是计算你需要一个索引之前(或之后)的组合数量。
当然,你说的52种组合中的3种是正确的。现在让我们列举一下b1,b2,b3之前的数量:
b1
。您有第一张卡的b1
选项(因为您从0开始),并且对于这些选项中的每一个b1_
,您都52-b1_
选择2
组合。因此,此数字是b1_
从0
到b1-1
的总和超过所述二项式系数的总和。通过一些数学知识,您可以为此得出一个封闭的公式,而无需实际计算总和。 b1
的第一张卡和具有低于b2
的索引的第二张卡的所有组合。这又是一个总和,但更容易。您可以选择第一张卡片(b1
)和b2-b1
(可能在一张卡片之前关闭,在实施之前检查它)第二张卡片的选项。对于每个选项(总和超过b2_
),您有第三张卡的52-b2
选项。这是连续数字的总和,得到一个封闭的公式很简单(提示:从n
开始的第一个1
数字的总和是n*(n+1)/2
,从1开始的连续数字是从1
开始的两个总和之间的差异。b1
和b2
以及第三张卡片小于b3
的组合数量。这很简单,因为该总和恰好是b3
。您现在唯一需要做的就是添加每个项目的结果,并获得索引。我建议你拿一张纸,按照建议进行数学计算,然后得到一个简单,易于评估的公式。
答案 1 :(得分:0)
如果您只想分配并获得标准套牌中任意3张不同卡片的唯一ID,则无需计算各种套装的组合数量。
让牌组中的牌分配1到52。
你可以以编程方式执行:
int getSetId (int card1, int card2, int card3){
if (card1 == card2 || card2 == card3 || card1 == card3)
//throw an exception
return (card1 * card2 * card3);
}
这将为您提供所有组合组合的唯一ID。
修改1:
如果由于乘数形成相同的产品而存在重复的id,而不是使用1到52,则可以使用前52个素数。
答案 2 :(得分:0)
我会忽略这样一个事实,即集合中的卡片必须是唯一的并且已经排序。然后您的索引只是card1 + 52 * card2 + 52 * 52 * card3
。对于格式良好的集合,并非每个索引都可以到达,并且分布向较低的数字倾斜。尝试hash = index % prime * 52 * 52 * 52 + index
均匀分发。尝试低素数。添加的索引部分确保散列将保持唯一。