魔术师发牌问题的简介:
一位魔术师掏出一叠扑克牌,魔术师取出其中13张黑桃,洗好后,把牌面朝下。说:“我不看牌,只数一数就能知道每张牌是什么?”魔术师口中念一,将第一张牌翻过来看正好是A;魔术师将黑桃A放到桌上,继续数手里的余牌,第二次数1,2,将第一张牌放到这叠牌的下面,将第二张牌翻开,正好是黑桃2,也把它放在桌子上。第三次数1,2,3,前面二张牌放到这叠牌的下面,取出第三张牌,正好是黑桃3,这样依次将13张牌翻出,全部都准确无误。求解:魔术师手中牌的原始顺序是什么样子的?
直接来看实现代码:
魔术师发牌问题实际上也是一种约瑟夫问题,也是用循环链表来模拟解决
#include <stdio.h> #include <malloc.h> #define LEN sizeof (LinkList) //定义struct node这个类型的长度 #define cardnumber 13 typedef struct node //定义结构体 { int data; struct node *next; }LinkList; LinkList* create(int m) //创建循环链表 { LinkList *head,*p1,*p2; int i; head=p1=(LinkList*)malloc(LEN); head->data=0; for(i=1;i<m;i++) { p2=(LinkList*)malloc(LEN); p2->data=0; p1->next=p2; p1=p2; } p2->next=head; return head; } void magician(LinkList* start,int m) //控制牌的顺序 { LinkList *p; int j; int countnumber = 2; p = start; p->data = 1; while(1) { for (j=0;j<countnumber;j++) { p = p->next; if(p->data != 0) //这里通过判断结点中data是够为0,来确定牌有没有被发出去,很巧妙的思想 { j--; } } if (p->data == 0) //data为0时,为其填入牌的点数 { p->data = countnumber; countnumber++; if (countnumber == m+1) break; } } } int main() //主函数 { int i; LinkList *p; p = create(cardnumber); magician(p,cardnumber); for (i=0;i < cardnumber;i++) // 打印 { printf("blackheart%3d\n",p->data); p = p->next; } return 0; }
运行结果: