这可能有点神秘,但我有一个非常具体的问题。首先是我当前的设置
即在我的卡片模拟器中,我以4套8个牌向4名玩家交易32张牌。所以每位玩家8张牌。 有4种标准套装(黑桃,帽子等) 我目前的实施周期投出了32个中的8个的所有组合 女巫给了我很多可能性。 即第一个玩家可以拥有10518300个不同的牌。 然后第二个可以发出735471个不同的牌。 第三名玩家然后是12870手。 最后第四个只能有1个 给了我一个总共9.9561092e + 16种不同的独特方式来处理一副32张牌给4名玩家。如果卡的顺序无关紧要。
在4 Ghz处理器上,即使每次可能有1个滴答,我也需要半年时间。
然而,我想通过交换钻石,黑客和黑桃来简化这种卡的交易。这意味着向玩家1处理8个仇恨相当于交易8个黑桃。 (请注意,这不适用于俱乐部)
我正在寻找一种方法来生成它。因为这会将第一只手的可能性降低至少6倍。我目前的实现是在c ++中。 但请随意用不同的语言回答
/** http://stackoverflow.com/a/9331125 */
unsigned cjasMain::nChoosek( unsigned n, unsigned k )
{
//assert(k < n);
if (k > n) return 0;
if (k * 2 > n) k = n-k;
if (k == 0) return 1;
int result = n;
for( int i = 2; i <= k; ++i ) {
result *= (n-i+1);
result /= i;
}
return result;
}
/** [combination c n p x]
* get the [x]th lexicographically ordered set of [r] elements in [n]
* output is in [c], and should be sizeof(int)*[r]
* http://stackoverflow.com/a/794 */
void cjasMain::Combination(int8_t* c,unsigned n,unsigned r, unsigned x){
++x;
assert(x>0);
int i,p,k = 0;
for(i=0;i<r-1;i++){
c[i] = (i != 0) ? c[i-1] : 0;
do {
c[i]++;
p = nChoosek(n-c[i],r-(i+1));
k = k + p;
} while(k < x);
k = k - p;
}
c[r-1] = c[r-2] + x - k;
}
/**http://stackoverflow.com/a/9430993 */
template <unsigned n,std::size_t r>
void cjasMain::Combinations()
{
static_assert(n>=r,"error n needs to be larger then r");
std::vector<bool> v(n);
std::fill(v.begin() + r, v.end(), true);
do
{
for (int i = 0; i < n; ++i)
{
if (!v[i])
{
COUT << (i+1) << " ";
}
}
static int j=0;
COUT <<'\t'<< j++<< "\n";
}
while (std::next_permutation(v.begin(), v.end()));
return;
}
要求是从词典编号我可以取回原始数组。 即便是最轻微的优化也可以帮助我的蒙托卡罗模拟我希望。