• 8,约瑟夫斯(Josephus)问题


      据说著名犹太历史学家 Josephus有过以下的故事:在罗马人占领乔塔帕特后,39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被人抓到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止。
      然而Josephus 和他的朋友并不想遵从,Josephus要他的朋友先假装遵从,他将朋友与自己安排在第16个与第31个位置,于是逃过了这场死亡游戏。
    实现思路:
    1)利用环形链表模拟,出列表示自杀。
    2)First指正移到开始数数位置,辅助指针helpPointer移到First前一个位置,也就三环形链表末尾 helpPointer.Next=First
    3)开始数数,First = First.Next helpPointer = helpPointer.Next; 两个指针一起移动,First指向哪个节点出列
    4)First == First.Next 表示已有一个元素
    C#代码实现:
      1 using System;
      2 using System.Collections.Generic;
      3 using System.Text;
      4 
      5 namespace 数据结构
      6 {
      7     public class CircleLinked
      8     {
      9         //创建头指针
     10         private Node First { get; set; }
     11         //创建环形链表
     12         public void Add(int nums)
     13         {
     14             if (nums < 1)
     15             {
     16                 Console.WriteLine("至少需要一个节点");
     17                 return;
     18             }
     19             //创建辅助指针
     20             Node curNode = null;
     21             for (int n = 1; n <= nums; n++)
     22             {
     23                 Node node = new Node(n);
     24                 if (n == 1)
     25                 {
     26                     //First和curNode指针指向第一节点
     27                     First = node;
     28                     curNode = First;
     29                     //指向自己形成环路
     30                     curNode.Next = First;
     31                     continue;
     32                 }
     33                 //上一节点断开环路,Next指向下一节点
     34                 curNode.Next = node;
     35                 //curNode指针移指向下一节点
     36                 curNode = node;
     37                 //指向第一个节点,形成环路
     38                 curNode.Next = First;
     39             }
     40         }
     41 
     42         //打印环形链表
     43         public void Scan()
     44         {
     45             if (First == null)
     46             {
     47                 Console.WriteLine("空链表");
     48             }
     49             //创建辅助指针
     50             var curNode = First;
     51             while (true)
     52             {
     53                 Console.Write($"{curNode.No}	");
     54                 //如果Next地址三First说明已经到最后一个
     55                 if (curNode.Next == First)
     56                 {
     57                     break;
     58                 }
     59                 curNode = curNode.Next;
     60             }
     61         }
     62 
     63         /// <summary>
     64         /// 
     65         /// </summary>
     66         /// <param name="startNo">开始位置</param>
     67         /// <param name="countNums">数多少次</param>
     68         /// <param name="nums">数多少次</param>
     69         public void Josephus(int startNo, int countNums, int nums)
     70         {
     71             if (First == null || startNo < 1 || startNo > nums)
     72             {
     73                 Console.WriteLine("参数错误");
     74                 return;
     75             }
     76             //只有一个节点,直接输出
     77             if (First.Next == First)
     78             {
     79                 Console.WriteLine($"{First.No}");
     80                 return;
     81             }
     82             //辅助指针
     83             Node helpPointer = First;
     84             //First移到开始位置
     85             while (true)
     86             {
     87                 if (First.No == startNo)
     88                 {
     89                     break;
     90                 }
     91                 First = First.Next;
     92             }
     93             //辅助helpPointer指针移动到链表末尾
     94             while (true)
     95             {
     96                 if (helpPointer.Next == First)
     97                 {
     98                     break;
     99                 }
    100                 helpPointer = helpPointer.Next;
    101             }
    102             //出列
    103             bool flag = true;
    104             while (flag)
    105             {
    106                 //只剩下一个节点
    107                 if (First.Next == First)
    108                 {
    109                     flag = false;
    110                 }
    111                 else
    112                 {
    113                     //数数
    114                     for (int n = 1; n < countNums; n++)
    115                     {
    116                         First = First.Next;
    117                         helpPointer = helpPointer.Next;
    118                     }
    119                 }
    120                 //First指向的节点出列
    121                 Console.Write($"{First.No}	");
    122                 if (flag)
    123                 {
    124                     First = First.Next;
    125                     helpPointer.Next = First;
    126                 }
    127             }
    128         }
    129 
    130 
    131         public class Node
    132         {
    133             public int No { get; set; }
    134             public Node Next { get; set; }
    135             public Node(int no)
    136             {
    137                 this.No = no;
    138             }
    139         }
    140     }
    141 
    142     public class Josephus
    143     {
    144         public static void Main(string[] args)
    145         {
    146             var circle = new CircleLinked();
    147             Console.WriteLine("加入41个人");
    148             circle.Add(41);
    149             circle.Scan();
    150             Console.WriteLine("
    自杀顺序,最后两个个幸存");
    151             circle.Josephus(1, 3, 41);
    152         }
    153     }
    154 }
  • 相关阅读:
    洛谷 P2634 BZOJ 2152 【模板】点分治(聪聪可可)
    洛谷 P3819 松江1843路
    洛谷 P1005 矩阵取数游戏
    洛谷 P2712 摄像头
    洛谷 P2774 方格取数问题
    洛谷 P3369 BZOJ 3224 【模板】普通平衡树(Treap/SBT)
    洛谷 P2805 BZOJ 1565 植物大战僵尸
    洛谷 P2312 解方程
    洛谷 P3355 骑士共存问题
    洛谷 P2762 太空飞行计划问题
  • 原文地址:https://www.cnblogs.com/xiaojvhuang/p/12702683.html
Copyright © 2020-2023  润新知