Josephus problem(约瑟夫问题,丢手绢问题)
约瑟夫问题
约瑟夫环问题是一个数学应用题:已知n个人(以编号1,2,3.....,n)围坐在一张圆桌的周围。从编号为k的人开始报数,数到m的那个人出列:他的下一个人又从1开始报数,数到m的那个人又出列,以此规律重复下去,直到圆桌的人全部出列。通常解决这类问题时我们把编号从0-n-1,最后+1即为原问题的解。
一、算法描述:
约瑟夫环运作如下:
- 一群人围在一起坐成环状
- 从某个编号开始报数(如:K)
- 数到某个数(如:M)的时候,此人出列,下一个人重新报数
- 一直循环,直到所有人出列 ,约瑟夫环结束
二、解决此类问题的解法
C语言 模拟递归法
公式推导法
#include <stdio.h>
#include <stdlib.h>
struct _Node
{
int data;
struct _Node *next;
};
typedef struct _Node node_t;
typedef struct _Linklist
{
node_t *phead;
node_t *ptail;
int len;
} Linklist;
static node_t *GetNode(int i) //新建并初始化节点
{
node_t *pNode;
pNode = (node_t *)malloc(sizeof(node_t));
if (!pNode)
{
printf("Error,thememoryisnotenough!\n");
exit(-);
}
pNode->data = i;
pNode->next = NULL;
return pNode;
}
void init_list(Linklist *plist) //用第一个节点初始化循环单链表
{
node_t *p;
p = GetNode();
//printf("TheNewNodeis:%d\n",p->data);//****TEST****
plist->phead = p;
plist->ptail = p;
p->next = plist->phead;
plist->len = ;
}
static void Create_List(Linklist *plist, int n) //把其余数据添加到循环单链表中
{
int i = ;
node_t *pNew;
for (i = ; i <= n; i++)
{
pNew = GetNode(i);
/********TEST********
printf("TheNewNodeis:%d\n",pNew->data);
********TEST********/
plist->ptail->next = pNew;
plist->ptail = pNew;
pNew->next = plist->phead;
plist->len++;
}
printf("Completesthee-waycirculationchaintablethefoundation!\n");
}
void Print_List(Linklist *plist) //输出链表内容
{
node_t *pCur = plist->phead;
do
{
printf("The%dperson.\n", pCur->data);
pCur = pCur->next;
} while (pCur != plist->phead);
printf("ThelengthoftheList:%d\n", plist->len);
} // 约瑟夫回环函数实现 void joseph(Linklist *plist, int m) //约瑟夫回环函数实现
{
node_t *pPre = plist->ptail;
node_t *pCur = plist->phead;
int i;
while (plist->len != )
{
i = ;
while (i < m - )
{
pPre = pPre->next;
i++;
}
pCur = pPre->next;
pPre->next = pCur->next;
free(pCur);
plist->len--;
}
printf("Thelastoneis:%d\n", pPre->data);
}
int main()
{
int n = ;
printf("PleaseinputtheLengthoftheCirclelist:");
scanf("%d", &n);
int m = ;
printf("PleaseinputtheStoppoint:");
scanf("%d", &m);
Linklist pList;
init_list(&pList);
Create_List(&pList, n);
Print_List(&pList);
joseph(&pList, m);
return ;
}
三、OJ 例题
题目描述

解题思路:
1<=n<1000发现数据量不大,直接模拟游戏求出最后一个人
下面是非递归使用for循环代码
#include <stdio.h>
#include <stdlib.h> int main()
{
int n;
while (scanf_s("%d", &n) == )
{
int len, i, j=;
int count = n;//当前存在的人数 当count == 1剩下最后一个人 即为答案
int a[] = { };//初始化模拟数组
for (i = ; i < n; i++)//人数从1~n数组标示从0~n-1
{
if (count == )
break;
if (a[i] == )//a[i]==1表示这个人已经退出游戏
{
if (j % == )
{
a[i] = ;
count--;//删掉一个人
}
else
{
if (i + >= n)//数组循环即 当i往下大于人数n时需要从0开始 但是由于是for 循环i会++ 所以i置为-1
i = -;
}
j++;
}
else
{
if (i + >= n)
i = -;//同上
}
if (i == n-)
i = -;//同上
}
for (i = ; i < n; i++)
if (a[i]==)
printf("%d\n", i + );
}
}
非递归使用while循环
#include <stdio.h>
#include <stdlib.h> int main()
{
int n;
while(scanf("%d",&n)==)
{
int i=,len,a[]={};
int flag=;
len=n-;
while(len)
{
if(a[i]==)
{
if(flag==)
{
i++;
if(i>n)
i=;
flag=;
}
else
{
a[i]=;
i++;
if(i>n)
i=;
flag=;
len--;
}
}
else
{
i++;
if(i>n)
i=;
}
}
for(i=;i<=n;i++)
if(a[i]==)
printf("%d\n",i);
}
}
题目数字较大的时候可以采用公式推导法,参考下面链接的博客
https://blog.csdn.net/u011500062/article/details/72855826
Josephus problem(约瑟夫问题,丢手绢问题)的更多相关文章
- 约瑟夫问题(Josephus Problem)的两种快速递归算法
博文链接:http://haoyuanliu.github.io/2016/04/18/Josephus/ 对,我是来骗访问量的!O(∩_∩)O~~ 约瑟夫问题(Josephus Problem)也称 ...
- 算法Sedgewick第四版-第1章基础-017一约瑟夫问题(Josephus Problem)
/************************************************************************* * * Josephus problem * * ...
- Bloomberg面经准备: Josephus problem
Given a circular single linked list.Write a program that deletes every kth node until only one node ...
- josephus Problem 中级(使用数组模拟链表,提升效率)
问题描写叙述: 在<josephus Problem 0基础(使用数组)>中.我们提出了一种最简单直接的解决方式. 可是,细致审视代码之后.发现此种方案的效率并不高,详细体如今.当有人出局 ...
- Josephus Problem的详细算法及其Python、Java实现
笔者昨天看电视,偶尔看到一集讲述古罗马人与犹太人的战争--马萨达战争,深为震撼,有兴趣的同学可以移步:http://finance.ifeng.com/a/20170627/15491157_0. ...
- python玩丢手绢问题,出局的顺序
# 丢手绢问题# 游戏规则: 有N个小朋友玩丢手绢游戏,做成一圈,从第一个小朋友开始数数,从一开始数,数到指定数字的小朋友要出列,然后下一个小朋友继续从1开始数,依次类推,算出最后一个留下来的小朋友是 ...
- NC207040 丢手绢
NC207040 丢手绢 题目 题目描述 "丢丢丢手绢,轻轻地放在小朋友的后面,大家不要告诉她,快点快点抓住她,快点快点抓住她." 牛客幼儿园的小朋友们围成了一个圆圈准备玩丢手绢的 ...
- 约瑟夫(环)问题(Josephus problem)
问题描述:皇帝决定找出全国中最幸运的一个人,于是从全国选拔出 n 个很幸运的人,让这 n 个人围着圆桌进餐,可是怎么选择出其中最幸运的一个人呢?皇帝决定:从其中一个人从 1 开始报数,按顺序数到第 k ...
- LightOJ - 1179 Josephus Problem(约瑟夫环)
题目链接:https://vjudge.net/contest/28079#problem/G 题目大意:约瑟夫环问题,给你n和k(分别代表总人数和每次要数到k),求最后一个人的位置. 解题思路:因为 ...
随机推荐
- 使用引导扇区维护工具BOOTICE编辑系统启动列表BCD文件
使用引导扇区维护工具BOOTICE编辑系统启动列表BCD文件 系列文章: 笔记本电脑提速之加装内存条.SSD固态硬盘.光驱位换SSD固态硬盘 笔记本ThinkPad E430c加装内存和SSD固态硬盘 ...
- LeetCode 171. Excel Sheet Column Number (Excel 表格列数字)
Related to question Excel Sheet Column Title Given a column title as appear in an Excel sheet, retur ...
- 5分钟Serverless实践 | 构建无服务器的敏感词过滤后端系统
前言 在上一篇“5分钟Serverless实践”系列文章中,我们介绍了什么是Serverless,以及如何构建一个无服务器的图片鉴黄Web应用,本文将延续这个话题,以敏感词过滤为例,介绍如何构建一个无 ...
- Domain-specific language 领域特定语言
https://en.wikipedia.org/wiki/Domain-specific_language A domain-specific language (DSL) is a compute ...
- C语言strdup()函数:复制字符串【转】
本文转载自:http://c.biancheng.net/cpp/html/166.html 头文件:#include <string.h> 定义函数:char * strdup(cons ...
- ubuntu16.04下配置静态ip
ubuntu下配置静态ip 1.先获取ip基本信息 ifconfig enp3s0 Link encap:以太网 硬件地址 2c:4d:54:65:de:6e inet 地址:192.168.199. ...
- [python基础] csv.wirterow()报错UnicodeEncodeError
python在安装时,默认的编码是ascii,当程序中出现非ascii编码时,python的处理常常会报这样的错,python没办法处理非ascii编码的,此时需要自己设置将python的默认编码,一 ...
- 洛谷 P1498 南蛮图腾 —— 模拟
题目:https://www.luogu.org/problemnew/show/P1498 大约一年前该做的题...现在来填一下坑: 然而不怎么会模拟!还滚去看TJ了: 就是翻倍复制: \ 这个符号 ...
- nodejs在windows下的安装
Windowv 上安装Node.js Windows 安装包(.msi) : 32 位安装包下载地址 : http://nodejs.org/dist/v0.10.26/node-v0.10.26-x ...
- 等价表达式 2005年NOIP全国联赛提高组(栈模拟)
P1054 等价表达式 题目描述 明明进了中学之后,学到了代数表达式.有一天,他碰到一个很麻烦的选择题.这个题目的题干中首先给出了一个代数表达式,然后列出了若干选项,每个选项也是一个代数表达式,题目的 ...