魔术师发牌问题的简介:
一位魔术师掏出一叠扑克牌,魔术师取出其中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;
}
运行结果: