扑克牌和掷骰子
1)题目:扑克牌的顺子
从扑克牌中随机抽5张牌,判断是不是一个顺子,即这5张牌是不是连续的。2-10 为数字本身,A 为1,J为11,Q 为12,K 为13,而大小王可以看成任意数字。
2)分析:
思路一:排序法,其中大小王看成0。然后,统计0个数,和数字间隔数,如果有重复(对子)则返回失败。间隔数小于等于2则成功,否则失败。
思路二:Hash法,类似排序。
3)源码:
注意:sort(int array[],array+nLength,comp); //注意添加 <algorithm> using namespace std;
qsort(int array[],nLength,sizeof(array[0]),compare); //自带的
#include <iostream>#include <algorithm>using namespace std;//函数功能 : 从扑克牌中随机抽5张牌,判断是不是一个顺子//函数参数 : pCards为牌,nLen为牌的张数//返回值 : 是否顺子int comb(const int *x,const int *y){return x<y; //}int cmp(const void *x,const void *y){return *(int *)x - *(int *)y; //}bool IsContinuous(int *pCards, int nLen){if(pCards == NULL || nLen <= 0)return false;//sort(pCards, pCards + nLen,comb); //调用标准库的排序算法 qsort(pCards,nLen,sizeof(pCards[0]),cmp); //for(int i=0;i<nLen;++i) // cout<<pCards[i]<<" "; int i;int zeroCount = 0; //大小王用0表示int capCount = 0; //间隔数//统计0的个数for(i = 0; i < nLen; i++){if(pCards[i] == 0)zeroCount++;elsebreak;}//统计间隔数int preCard = pCards[i]; for(i = i + 1; i < nLen; i++){int curCard = pCards[i];if(preCard == curCard) //与前一张牌比较return false;elsecapCount += curCard - preCard - 1; //累加间隔数preCard = curCard;}return (zeroCount >= capCount)? true: false; //只要王的个数大于间隔数}int main(){int pCards[]={1,2,3,4,5};int pCards2[]={1,2,8,4,12};int i=IsContinuous(pCards,5);bool j=IsContinuous(pCards2,5);cout<<i<<endl;cout<<j<<endl;}
)题目:n 个骰子的点数。把n 个骰子扔在地上,所有骰子朝上一面的点数之和为S。输入n,
2)分析:
用PN,S来表示N个骰子,顶面数字之和为S出现的概率,则:
PN,S=aN,S/6^N
其中aN,S为N个骰子顶面数之和为S的状态的数量,6^N为总的状态数量,因为每个骰子有6种状态,N个骰子组成的状态数就是6^N。
下面给出求ai,j的递推公式,即求i(1=<i<=N)个骰子顶面数之和为j(i=<j<=6*i)时的状态数量:
ai,j= ai-1,j-1//第i个骰子顶面为1时,其他i-1个骰子顶面数之和为j-1时的状态数量
+ ai-1,j-2 //第i个骰子顶面为2时,其他i-1个骰子顶面数之和为j-2时的状态数量
+ ai-1,j-3//第i个骰子顶面为3时,其他i-1个骰子顶面数之和为j-3时的状态数量
+ ai-1,j-4//第i个骰子顶面为4时,其他i-1个骰子顶面数之和为j-4时的状态数量
+ ai-1,j-5//第i个骰子顶面为5时,其他i-1个骰子顶面数之和为j-5时的状态数量
+ ai-1,j-6//第i个骰子顶面为6时,其他i-1个骰子顶面数之和为j-6时的状态数量
其中递推公式中i>1。
对于任意的1=<i<=N,j<=0或j<i或j>6*i,ai,j=0。
3)源码:
非递归求解:
#include <iostream>#include <math.h>using namespace std;void PrintSumProbabilityOfDices(unsigned int n) { const unsigned int MAX=12; //max number of dices if(n>MAX) { printf("Overflow!\n"); return; }; unsigned int a[MAX+1][6*MAX+1]; unsigned int i,j,k; memset(a,0,sizeof(a)); /* a[i][j] i代表骰子个数 j代表 i个骰子可能出现的骰子的数量 * */ for(j=1;j<=6;j++)//只有一个骰子的时候,每一个数出现的次数都是 1 a[1][j]=1; for(i=2;i<=n;i++) //第 i个 骰子出现 for(j=i;j<=6*i;j++) //j为所有骰子可以出现的次数 { a[i][j]=0; //初始化要求的 数 for(k=1;k<=6&&k<=j;k++) //k代表 第 i个骰子出现的可能点数 k<=j 说明 不能超过当前所求所有骰子 总点数 a[i][j]+=a[i-1][j-k]; //其他 i-1个骰子 出现j-k 点的次数 } unsigned int nTotal=pow(6,n); for(i=n;i<=6*n;i++) printf("Sum=%d,Probability=%.15lf\n",i,a[n][i]*1.0/nTotal); } int main(){PrintSumProbabilityOfDices(2);}