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),求最后一个人的位置. 解题思路:因为 ...
随机推荐
- 【原创】分布式之缓存击穿 【原创】自己动手实现静态资源服务器 【原创】自己动手实现JDK动态代理
[原创]分布式之缓存击穿 什么是缓存击穿 在谈论缓存击穿之前,我们先来回忆下从缓存中加载数据的逻辑,如下图所示 因此,如果黑客每次故意查询一个在缓存内必然不存在的数据,导致每次请求都要去存储层去查 ...
- 【Android自己定义View实战】之自己定义超简单SearchView搜索框
[Android自己定义View实战]之自己定义超简单SearchView搜索框 这篇文章是对之前文章的翻新,至于为什么我要又一次改动这篇文章?原因例如以下 1.有人举报我抄袭,原文链接:http:/ ...
- 放大的X(杭电2565)
/*放大的X 请你编程画一个放大的'X'. Input 输入数据第一行是一个整数T,表示有T组測试数据: 接下来有T行,每行有一个正奇数n(3 <= n <= 79).表示放大的规格. O ...
- 重写description方法
//重写description方法 //description建议大家在实际开发中都要重写这种方法.然后将类中有意义的成员变量打印出来,这样很方便我们调试程序 -(NSString *)descrip ...
- Android 布局属性大全
常用属性汇总: android:hint 设置EditText为空时输入的提示信息 android:gravity 对该view内容的限定:靠上 下 左 右 andro ...
- How do browser cookie domains work?
https://stackoverflow.com/questions/1062963/how-do-browser-cookie-domains-work 答案一 Although there is ...
- .NET连接数据库实例
.NET连接数据库实例 keleyi.com 柯乐义 本实例实现了从MSSQL 2005数据库读取数据并显示在页面上的功能.在Visual Studio 2010上测试成功.源代码下载:http:// ...
- .NET平台下Redis使用(二)【StackExchange.Redis学习】
Program.cs内容: using Newtonsoft.Json; using StackExchange.Redis; using System; using System.Data; usi ...
- 【模板】 倍增lca
虽然很基础,但是还是复习了一下,毕竟比树剖好写... 代码: #include<iostream> #include<cstdio> #include<cmath> ...
- java SWing事件调用的两种机制
Java(91) /** * java swing中事件调用的两种机制: * (一)响应机制 * (二)回调机制 */ package test; import java.awt.*; impo ...