本文主要是介绍魔术师的卡牌,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
此题目的:
- 加深对循环链表的理解
- 增强对链表的使用能力
看到很多篇文章把这到问题写的不清不楚的,今天特意把这个题目叙述给大家,然后自己先想一想要怎么做。再来看题解。
某天,有个魔术师从一套完整的卡牌将13张张桃卡牌全部拿了出来,洗好了牌之后,展示给众人说,他对众人说,我不用看牌,只需要数数,就可以知道这张牌是什么,于是他把13张牌牌面向下,“第一张牌是 黑桃A”,他如此说道,然后把黑桃A扔到桌子上,此时手上还有12张牌,然后他又说道“从上往下数第二张牌是 黑桃2”,他把从上往下数的第一张牌拿到第12张牌,也就是最后一张牌的下面(没有看),然后翻看第二张牌,果真是是 黑桃2,然后他有说了“从上往下数第三张牌是 黑桃3”,于是他把前面两张牌按照原来的顺序放在最后一张牌的下面,翻开了第三张牌,果真是是 黑桃3,然后魔术师又把这张 黑桃3 扔到桌子上,就这样,反反复复,翻开了 13 张牌,魔术师说的每一张牌都是准确的,那么,他是怎么做到的呢?
问题转化:
其实就是一个魔术师在做翻牌之前,他是怎么放牌的问题。
首先,我们注意到,魔术师每次翻看完扑克牌以后,就把它扔到桌子上了,那么总的牌数就会减少。
其次,我们还注意到,每次魔术师翻看扑克牌之前都会把上面不翻看的扑克牌放到最下面。
魔术师做了 三 个动作,放牌 翻牌 扔牌,就这么重复这三种动作,所以答案肯定就在这个过程里面,假设我们固定 13 个盒子,将其标号为 1 - 13,如果盒子里面的扑克牌被翻看了,就为这个盒子盖上黑布,不准再碰了也不能在数数的时候算他一个,我们发现 当我们翻看 黑桃A 2 3 4 的时候,都是在 13 以内的,但是要翻 黑桃5 时,发现已经到最后一个盒子了,怎么办呢?我们想想魔术师怎么做的?---(放牌),没错,我们倒回去,从 1 号盒子开始,但是 1 号盒子已经被翻过了,不能再动它了,那这时候怎么办呢?死鬼,放聪明点,我们跳过这个 1 号格子不把它,到下一个盒子去,如果下一个盒子还这样我们继续跳过,前面留了这么多空,总会有没有翻过牌的盒子吧!(注意:无形中我们使用到了循环)
一张图看看:
需要用到循环,需要使用链表所以我们在开始解这项魔术之前要先定义循环链表哦!
#include <iostream>
#include <iomanip>
#include <malloc.h>
#include <memory.h>
#define N 13
using namespace std;//定义链表结构体
typedef struct Node{int data;struct Node *Next;
}Node,*LinkList;//初始化循环链表
LinkList InitLinkList(LinkList L)
{L = (Node*)malloc(sizeof(Node));L->Next = L;Node *p;for(int i = 0;i<N;i++){p = (Node*)malloc(sizeof(Node));p->data = 0;p->Next = L->Next;L->Next = p;}return L;
}int main()
{LinkList L = InitLinkList(L);int i;Node *p = (Node*)malloc(sizeof(Node));p = L->Next;p->data = 1;//放牌 翻牌 扔牌(就是跳过它,你也可以理解成跳牌)的过程for(int num = 2;num<=N;num++){i = 0;while(i < num){p = p->Next; if(p->data == 0)i++;}p->data = i;}p = L->Next;//遍历while(p!=L){cout<<p->data<<" ";p = p->Next;}
}
怎么样?有趣吧!是的,学算法也可以这么有趣!
这篇关于魔术师的卡牌的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!