鱼C论坛

 找回密码
 立即注册

魔术师发牌问题附注解

已有 178 次阅读2019-8-19 22:12

魔术师发牌问题的简介:一位魔术师掏出一叠扑克牌,魔术师取出其中13张黑桃,洗好后,把牌面朝下。说:“我不看牌,只数一数就能知道每张牌是什么?”魔术师口中念一,将第一张牌翻过来看正好是A;魔术师将黑桃A放到桌上,继续数手里的余牌,第二次数1,2,将第一张牌放到这叠牌的下面,将第二张牌翻开,正好是黑桃2,也把它放在桌子上。第三次数1,2,3,前面二张牌放到这叠牌的下面,取出第三张牌,正好是黑桃3,这样依次将13张牌翻出,全部都准确无误。求解:魔术师手中牌的原始顺序是什么样子的?

#include <stdio.h>
#include <stdlib.h>

#define cardnum 13 // 一种花色的牌数

typedef struct node {
    int data ;
    struct node *next ;
} node ;

node *createlist (node *head) // 尾插法建立循环链表,不多赘述
{
    node *tmp = NULL ;
    node *add = NULL ;
    head = (node *)malloc(sizeof(node));
    tmp = head ;
    for (int i = 0 ; i < cardnum ; i++)
    {
        add = (node *)malloc(sizeof(node));
        add->data = 0 ;
        tmp->next = add ;
        tmp = add ;
    }
    tmp->next = head->next ;
    return tmp->next ;
}

void magic (node *head) // 这个算法充分展示了循环链表的伟大之处
// 极其建议在纸上进行推演,会更快发现其算法的智慧之处,强烈建议
{
    node *target = NULL ;
    int i ;
    int countnum = 2 ; 
    head->data = 1 ; // 翻开第一张牌,记录其数字,数据域被变动的结点后期会被忽略
    target = head ; // 目标指针变量
    while (1)
    {
        for (i = 0 ; i < countnum ; i++) // 第一次执行时,进行两次迭代,继而跳脱以翻开第二张牌
        {
            target = target->next ; // 步进目标指针
            if (target->data != 0) // 如果数据域被改动过,即亮出来的卡片,则忽略它,使用i--不计这次迭代
            {
                i-- ;
            }
        }
target->data = countnum ;
// 来到我们准备翻开的牌,进行赋值操作
        countnum ++ ; // 增加点数
        if (countnum == 14) // 当点数为13的牌确立后,则在自增之后跳脱
        {
             break ;
        }
    }
}

int main ()
{
    node *head = NULL ;
    head = createlist(head);
    magic(head);
    printf("按以下顺序排列:\n");
    for (int i = 0 ; i < cardnum ; i++)
    {
        printf("黑桃%d  ",head->data);
        head = head->next ;
    }
}

路过

鸡蛋

鲜花

握手

雷人

评论 (0 个评论)

facelist

您需要登录后才可以评论 登录 | 立即注册

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-3-29 21:23

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

返回顶部