1.概念描述
**约瑟夫环:**已知n个人围成一圈,从编号为k的人开始报数,凡报数为m的人离开圈并从下一个人从1开始数,数到m的那个人再次出圈,反复循环直到圈里只剩下一个人结束。
2.实战题目
这里引入一个之前做过的一道题目:
7-28 猴子选大王 (20分)
一群猴子要选新猴王。新猴王的选择方法是:让N只候选猴子围成一圈,从某位置起顺序编号为1~N号。从第1号开始报数,每轮从1报到3,凡报到3的猴子即退出圈子,接着又从紧邻的下一只猴子开始同样的报数。如此不断循环,最后剩下的一只猴子就选为猴王。请问是原来第几号猴子当选猴王?
输入格式:
输入在一行中给一个正整数N(≤1000)。
输出格式:
在一行中输出当选猴王的编号。
输入样例:
11
输出样例:
7
解法一:数组
#include<stdio.h>
int main()
{
int i=0,t=0;//i表示循环,t为中间量。
int N=0;//N表示猴子数量
int count=0;//表示出圈的猴子数量
scanf("%d",&N);
int arr[N];//对数组进行统一的初始化,以便后面计算
for(i=0;i<N;i++)
{
arr[i]=0;
}
while(count<N-1)//当圈里猴子只有一个时不再执行代码
{
for(i=0;i<N;i++)
{
if(N!=1&&arr[i]==0)//判断是否满足条件
{
t++;
if(t%3==0)//这是满足出圈条件的猴子
{
t=0;
arr[i]=1;//让这个猴子出圈
count++;
}
}
if(count==N-1)break;
}
}
//输出结果
for(i=0;i<N;i++)
{
if(arr[i]==0)//猴王
{
printf("%d\n",i+1);
}
}
return 0;
}
上面写的代码为了便于理解并未优化,如有问题请及时指正,感谢大佬。
解法二:循环链表
下面展示一些 内联代码片
。
// A code block
var foo = 'bar';
// An highlighted block
#include <stdio.h>
#include <stdlib.h>
//声明链表节点
typedef struct node
{
int number;//存储猴子的位号
struct node *next;//定义结构体指针,指向下一个节点
}Node;
/*创建链表节点的函数*/
Node* CreatNode(int x)
{
Node *p;
p = (Node*)malloc(sizeof(Node));
p->number = x;//给猴子的位号赋值
p->next = NULL;
return p;
}
//创建环形链表,存放整数1到n
Node* CreatJoseph(int n)
{
Node *head,*p,*q;
int i;
for(i = 1; i <= n; i++)//使用循环创建链表节点
{
p = CreatNode(i); //创建一个链表节点,给number赋值
if(i == 1)//如果是头结点
head = p;
else//不是头结点,则指向下一个节点
q->next = p;//这里的q->next是上一个节点的地址
q = p;
}
q->next = head;//末尾节点指向头结点,构成循环链表
return head;
}
//开始进行运算
void RunJoseph(int n)
{
Node *p,*q;
p = CreatJoseph(n);//创建循环链表
int i;
while(p->next != p)//循环条件,当前链表数目大于1
{
for(i = 1; i <2; i++)//开始计数
{
p = p->next;//p表示第二只猴子
}
//第3个人出圈
q = p->next;//q表示第三只猴子
p->next = q->next;//q指向的下一个是第四只猴子
p = p->next;//下一次从第四只猴子开始
free(q);//把第三只猴子踢出链表。
}
//这里的for循环这样写的原因是,地址操作。
printf("%d",p->number);//输出猴子之王。
}
int main()
{
int n;
scanf("%d",&n);
RunJoseph(n);
return 0;
}
解法三:函数递归()
思路:推导出递归公式即可
-------------------后续再敲这个代码吧,递归人脑袋大。。。
解法四:迭代代码
思路:与函数递归相似,使用for循环搞出来。
下面展示一些 内联代码片
。
// A code block
var foo = 'bar';
// An highlighted block
#include <stdio.h>
int main()
{
int m,i,s=0;
scanf("%d",&m);
for(i=1 ; i<=m ; i++)
s = (s+3) % i ;
printf("%d\n",s+1);
return 0 ;
}
3.总结
额。。。。。。
希望有错误的地方大佬及时指出,我及时改过来,嘿嘿。