zoukankan      html  css  js  c++  java
  • 循环链表-约瑟夫环

    问题来历:据说著名犹太历史学家 Josephus有过以下的故事:在罗马人占领乔塔帕特后,39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止。然而Josephus 和他的朋友并不想遵从。首先从一个人开始,越过k-2个人(因为第一个人已经被越过),并杀掉第k个人。接着,再越过k-1个人,并杀掉第k个人。这个过程沿着圆圈一直进行,直到最终只剩下一个人留下,这个人就可以继续活着。问题是,给定了和,一开始要站在什么地方才能避免被处决?Josephus要他的朋友先假装遵从,他将朋友与自己安排在第16个与第31个位置,于是逃过了这场死亡游戏。

    /*********************************************************************************
     *      Copyright:  (C) 2014 lingyun-emb
     *                  All rights reserved.
     *
     *       Filename:  13-3-1.cpp
     *    Description:  This file is about circular list.已知n个人(以编号1,2,3,...,n分别表示)
     *    围坐在一张圆桌周围.从编号为k的人开始报数,数到m的那个人出列,他的下一个人又从1开始报
     *    数,数到m的那个人出列,如此反复,直到圆桌周围的人全部出列。
     *                 
     *        Version:  1.0.0(2014年10月28日)
     *         Author:  zbq <2583105532@qq.com>
     *      ChangeLog:  1, Release initial version on "2014年10月28日 15时20分58秒"
     *                 
     ********************************************************************************/
    #include <iostream>
    #include <stdio.h>
    #include <stdlib.h>
    using namespace std;
    
    typedef struct node
    {
        int data;
        struct node *next;
    }node,*plist;
    
    /* n为总人数,k为第一个开始报数的人的编号,从1开始,数到m的人出列 */
    void JOSEPHUS(int n,int k,int m)
    {
        /* p为当前节点,r为辅助节点,指向p的前驱节点*/
        plist p=NULL,r=NULL,curr=NULL;
    
        /* 建立循环链表 */
        p=(plist)malloc(sizeof(node));
        p->data = 0;
        p->next = p; //一个节点的循环链表
        curr = p;//p指向编号为0的节点
        for(int i=1;i<n;i++)
        {
            plist t = (plist)malloc(sizeof(node));
            t->data = i;
            t->next = curr->next;
            curr->next = t;
            curr = t; //循环结束后curr指向编号0的节点,t指向编号n-1的节点。
        }
    
        r=curr; //把当前指针移到第一个报数的人
        while(k--) //第一次从编号为k的人开始报数,所以要跳过前k-1个人。
        {
            r=p;
            p = p->next;
        }
        while(n--) //直到圆桌周围的n个人全部出列
        {
            for(int s=m-1;s--;r=p,p=p->next); //从1开始报数,报到m的人出列,对应s从m-1到0的变化。
            r->next = p->next; //将报数为m的节点剔除链表
            printf("%d->",p->data);//输出该链表编号
            free(p);
            p = r->next;
        }
    }
    
    main()
    {
        JOSEPHUS(13,4,3);
    }


    详见:

    约瑟夫环问题两解

    抽杀问题(约瑟夫问题)

    约瑟夫问题的数学方法

     

  • 相关阅读:
    查看端口有没有被占用
    微信公众号2()
    How to insert a segment of noise to music file
    puppet practice
    Docker Commands
    LempelZiv algorithm realization
    The algorithm of entropy realization
    Java network programmingguessing game
    Deploy Openstack with RDO and Change VNC console to Spice
    puppet overview
  • 原文地址:https://www.cnblogs.com/zhanbiqiang/p/4057651.html
Copyright © 2011-2022 走看看