牌型种数
小明被劫持到X赌城,被迫与其他3人玩牌。
一副扑克牌(去掉大小王牌,共52张),均匀发给4个人,每个人13张。
这时,小明脑子里突然冒出一个问题:
如果不考虑花色,只考虑点数,也不考虑自己得到的牌的先后顺序,自己手里能拿到的初始牌型组合一共有多少种呢?请填写该整数,不要填写任何多余的内容或说明文字。
答案:3598180
对于A,2,3…J、Q、K这13种牌,小明拿到每种牌的张数可能为0、1、2、3或4张牌。共有5的13次方(1 220 703 125)种可能性,但其中只有每种牌张数总和为13的组合才为正确的组合,该组合数为3 598 180。
解法一
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cctype>
#include <vector>
#include <cstdlib>
using namespace std;
int main()
{
int i[20];
long long ans=0;
for(i[1]=0;i[1]<=4;i[1]++)
for(i[2]=0;i[2]<=4;i[2]++)
for(i[3]=0;i[3]<=4;i[3]++)
for(i[4]=0;i[4]<=4;i[4]++)
for(i[5]=0;i[5]<=4;i[5]++)
for(i[6]=0;i[6]<=4;i[6]++)
for(i[7]=0;i[7]<=4;i[7]++)
for(i[8]=0;i[8]<=4;i[8]++)
for(i[9]=0;i[9]<=4;i[9]++)
for(i[10]=0;i[10]<=4;i[10]++)
for(i[11]=0;i[11]<=4;i[11]++)
for(i[12]=0;i[12]<=4;i[12]++)
for(i[13]=0;i[13]<=4;i[13]++)
{
int t=0;
for(int j=1;j<=13;j++)
{
t+=i[j];
}
if(t==13)
{
ans++;
}
}
cout<<ans<<endl;
system("pause");
return 0;
}
解法二
#include<iostream>
using namespace std;
void perm(int cur, int& ctr, int sum);
int main()
{
int ctr=0;
int sum=0;
perm(1,ctr,sum);
cout<<ctr<<endl;
return 0;
}
/**
*cur为当前考虑到哪种牌,cur=1即考虑牌型为A的情况
*ctr统计正确的组合数
*sum统计当前牌的总数是否已经超过13,如超过则无需继续考虑子节点
*/
void perm(int cur, int& ctr, int sum)
{
if(sum>13)
return;
if(cur==14) //易错点,要将K(第13张牌)考虑完,即cur=14
{
if(sum==13) //易错点,排除总和不为13的组合方式
ctr++;
}
else
{
for(int i=0; i<=4; i++)
{
sum+=i;
perm(cur+1,ctr,sum);
sum-=i;
}
}
}
解法二的效率要明显优于解法一的效率。