约瑟夫环
据说著名犹太历史学家 Josephus有过以下的故事:在罗马人占领乔塔帕特后,39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止。然而Josephus 和他的朋友并不想遵从。首先从一个人开始,越过k-2个人(因为第一个人已经被越过),并杀掉第k个人。接着,再越过k-1个人,并杀掉第k个人。这个过程沿着圆圈一直进行,直到最终只剩下一个人留下,这个人就可以继续活着。问题是,给定了和,一开始要站在什么地方才能避免被处决?Josephus要他的朋友先假装遵从,他将朋友与自己安排在第16个与第31个位置,于是逃过了这场死亡游戏。
约瑟夫环 有很多解决方法这里主要是讲解利用数据结构中的循环链表进行模拟求解;
例题:
AC代码:
#include<stdio.h>
#include<stdlib.h>
#include<iostream>
using namespace std;
typedef struct node
{
int number;
int password;
struct node*next;
} node,*linklist;
linklist creat(int a)
{
int x,i;
linklist l=(linklist)malloc(sizeof(node));
l->number=1;
l->next=NULL;
scanf("%d",&x);
l->password=x;
linklist rear;
rear=l;
for(i=1; i<a; i++)
{
scanf("%d",&x);
linklist s=(linklist)malloc(sizeof(node));
s->password=x;
s->number=i+1;
s->next=NULL;
rear->next=s;
rear=s;
}
rear->next=l;
return l;
}
int getlen(linklist l)
{
linklist temp=l;
int cnt=0;
while(temp->next!=l)
{
cnt++;
temp=temp->next;
}
return cnt;
}
void operlist(linklist l,int a,int b)
{
linklist s;
int i;
for(i=0; i<a-2; i++)
{
l=l->next;
}
int cnt =getlen(l);
while(cnt)
{
if(b>0)
b--;
while(b)
{
l=l->next;
b--;
}
s=l->next;
b=s->password;
l->next=s->next;
printf("%d ",s->number);
free(s);
cnt--;
}
printf("%d \n",l->number);
}
int main()
{
linklist p;
int m,n,code=0;
printf("请输入人数:");
scanf("%d",&n);
printf("请输入m的初值:");
scanf("%d",&m);
p=creat(n);
operlist(p,m,code);
return 0;
}
代码具体就不讲解啦,毕竟是数据结构就是一些细节问题,很容易搞清楚。大家仔细想想肯定会懂的。
总结:
啊~~~,也快期中考试啦,数据结构还没有开始学,今天朋友让我看一下这个用链表模拟。花了两三个点才搞懂,自己果然是太菜啦。
或许ACM真的不适合我,希望科林能给我指一条明路!!!
告诫:
好好学。