魔术师发牌问题

魔术师发牌问题的简介:

一位魔术师掏出一叠扑克牌,魔术师取出其中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;
}

运行结果:


猜你喜欢

转载自blog.csdn.net/sinat_38486449/article/details/80242221