1、朴秀峰,模拟,问题求解与程序设计,程序举例,约瑟夫问题排列模拟发牌扑克牌中的顺子过桥问题,约瑟夫问题,问题描述有n 只猴子,按顺时针方向围成一圈选大王(编号从到 n),从第号开始报数,一直数到 m,数到 m 的猴子退出圈外,剩下的猴子再接着从 1 开始报数。就这样, 直到圈内只剩下一只猴子时,这个猴子就是猴王,编程求输入 n, m 后,输出最后猴王的编号。输入要求每行是用空格分开的两个整数,第一个是 n, 第二个是 m ( 0 m, n 300)。最后一行 是:0 0。输出要求对于每行输入数据(最后一行除外),输出数据也是一行,即最后猴王的编号。,约瑟夫问题,int aLoopMAX_NUM
2、+ 10; int n, m, i;while(1) (1) 读数据(2) 找猴王(1) 读数据scanf( %d%d, ,约瑟夫问题,(2) 找猴王 int nPtr = 0; for( i = 0; i n; i + ) /每次循环将 1 个猴子全赶出圈子,/最后被赶出的就是猴王int nCounted = 0;while( nCounted m ) /数出 m 个猴子while( aLoopnPtr = 0)/跳过已经出圈的猴子nPtr = ( nPtr + 1 ) % n;/到下一个位置nCounted +;/找到一只猴子nPtr = ( nPtr + 1 ) % n; /到下一个位置
3、nPtr -;/要回退一个位置if( nPtr 0 ) nPtr = n - 1;if( i = n-1 )/最后一只出圈的猴子 printf(%dn, aLoopnPtr); aLoopnPtr = 0; /猴子出圈,排列,问题描述大家知道,给出正整数 n,则 1 到 n 这 n 个数可以构成 n!种排列,把这些排列按照从 小到大的顺序(字典顺序)列出,如 n=3 时,列出 1 2 3, 1 3 2, 2 1 3, 2 3 1, 3 1 2, 3 2 1 六个排列。给出某个排列,求出这个排列的下 k 个排列,如果遇到最后一个排列,则下 1 排列为第1 个排列,即排列 1 2 3 n。比如:n
4、=3,k=2 给出排列 2 3 1,则它的下 1 个排列为 3 1 2,下2个排列为 3 2 1,因 此答案为 321。输入数据第一行是一个正整数 m,表示测试数据的个数,下面是 m 组测试数据,每组测试数据 第一行是 2 个正整数 n ( 1n1024 )和 k (1k64),第二行有 n 个正整数,是 1, 2, , n 的一个排列。输出要求对于每组输入数据,输出一行,n 个数,中间用空格隔开,表示输入排列的下 k 个排列。,排列,排列,求X=1, 2, 3, 4, 5, 6, 7 上排列 P= 2 6 3 7 5 4 1 的下一个排列Q从右到左找出比右边数字小的第一个数,即 3。再从右到
5、左考察比 3 大的最小的数,是 4 。将 3 与 4 对换位置,得 2647531 。将得到的排列 2647531 从 4 后面的 7531 从小到大排序得 1357 。把前缀 264 接在 1357 的前面得 2641357,它就是所求的排列 2637541 的下一个排列。例 2147635 的下 2 个排列是 2153467,排列,设 X = 1, 2 , , n ,求 P = a1a2an 的下一个排列:1) 从 an 开始,往左边找,直到找到某个 aj,满足 aj-1= 1 ,模拟发牌,问题描述随机发四手扑克牌,不包括大小王。,模拟发牌,#include #include #inclu
6、de struct card char suit;char face;typedef struct card Card;void fillDeck (Card *, char , char );void shuffle (Card *);void deal (Card *);,模拟发牌,void main()Card deck52;char face = A, K, Q, J, T, 9, 8, 7, 6, 5, 4, 3, 2;/* char suit = S, H, D, C; */char suit = 006, 003, 004, 005;fillDeck(deck, face, su
7、it);shuffle(deck);deal(deck);,模拟发牌程序填充牌面,void fillDeck(Card *wDeck, char wFace, char wSuit)int i;for (i=0; i52; i+)wDecki.face = wFacei%13;wDecki.suit = wSuiti/13;,模拟发牌程序洗牌,void shuffle(Card *wDeck)int i, j;Card temp;srand(time(NULL);for (i=0; i52; i+) j = rand()%52;temp.suit = wDecki.suit;temp.face
8、 = wDecki.face;wDecki.suit = wDeckj.suit;wDecki.face = wDeckj.face;wDeckj.suit = temp.suit;wDeckj.face = temp.face;,模拟发牌程序发牌,void deal (Card *wDeck)int i;printf(nn);for (i=0; i52; i+)printf(%c%c%c, wDecki.suit, wDecki.face, (i+1)%13=0 ? n : );,扑克中的顺子,问题描述从扑克牌中随机抽5张牌,判断是不是一个顺子,即这五张牌是不是连续的。2-10为数字本身,A
9、为1,J为11,Q为12,K为13,而大小王可以看成任意数字。,扑克中的顺子,bool IsContinuous(int* numbers, int length) if(numbers = NULL | length numberOfZero) ? false : true; ,扑克中的顺子,int compare(const void *arg1, const void *arg2) return *(int*)arg1 - *(int*)arg2;,过桥问题,U2 合唱团在 17 分钟内得赶到演唱会场,途中必需跨过一座桥,四个人从桥的同一端出发,你得帮助他们到达另一端,天色很暗,而他们只
10、有一只手电筒。一次同时最多可以有两人一起过桥,而过桥的时候必须持有手电筒,所以就得有人把手电筒带来带去,来回桥两端。手电筒是不能用丢的方式来传递的。四个人的步行速度各不同,若两人同行则以较慢者的速度为准。甲需花 1 分钟过桥,乙需花 2 分钟过桥,丙需花 5 分钟过桥,丁需花10 分钟过桥。他们要如何在 17 分钟内过桥呢?,过桥问题,n 个人要在晚上过桥,在任何时候最多两人一组过桥,每组要有一只手电筒。在这 n 个人中只有一只手电筒可以用,因此要安排以某种往返的方式来返回手电筒,使得更多的人可以过桥。每个人的过桥速度不同,每组的速度由速度慢的成员所决定。请确定一个策略,让 n 个人用最少的时间过桥。,思考题,【 Cola 】便利店给出以下的优惠:每3个空瓶可以换1瓶可口可乐。现在,你准备从便利店买一些可口可乐(n瓶),你想知道你最多可以从便利店拿到多少瓶可口可乐?以8瓶为例,可以获得多少?。你也可以从朋友(或店主)那里借一个空瓶,这样可以获得多少?【麻将的发牌及判断】 n*AAA+m*BCD+EE=胡了其中:mn不能同时为0,ABCDE不能同时在2-8区间,并且数目在14张。,