题目链接:5022: 约瑟夫
Description
在罗马人占领乔塔帕特后,39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止。然而Josephus 和他的朋友并不想遵从。他们该如何逃脱这场死亡游戏。
n个人(n<=100)围成一圈,从第一个人开始报数,数到m的人出列,再由下一个人重新从1开始报数,数到m的人再出圈,……依次类推,直到所有的人都出圈,请输出依次出圈人的编号.
Input
一行2个用空格隔开的整数n,m。
Output
一行用空格隔开的整数,表示出圈编号。
Sample Input
10 3
Sample Output
3 6 9 2 7 1 8 5 10 4
思路:
一开始认为数据范围不大,于是自己就直接模拟。但是无语,直接timelimit
看其他大佬所写的,一语点明我的思路。链表
上AC代码:
#include<bits/stdc++.h>
using namespace std;
struct node
{
int num;
node *nex; //记录下一位成员
};
int main()
{
int n,m;
cin>>n>>m;
node *head = NULL,*next,*off; //head记录第一个成员,next记录下一个成员,off记录上一个成员
for(int i = 1;i<=n;i++)
{
next = (node *)malloc(sizeof(node)); //创建一个空间
next->num=i; //对新创造的赋值
if(head == NULL) //如果没有第一个,那么就让next为第一个
{
head = next;
}
else //有第一个,就让上面一个的nex 指向现在这个
{
off->nex = next;
}
off = next; //要创造新的一个,所以需要重置上一个
}
off->nex = head; //让最后一个和第一个连起来
node *j=NULL;
int cnt = 0,ok = 0,k=0;
for(node *i = head;cnt<n;i = i->nex)
{
k++;
if(k==m) //如果是第m个
{
k = 0;
cnt++;
if(ok) cout<<' ';
ok = 1;
cout<<i->num;
if(j!=NULL) //因为这个已经被去除了,所以需要让他上一个指向下一个
{
j->nex = i->nex;
}
}
j = i;
}
return 0;
}
链表很轻松的帮我解决了收尾相连与去除中间元素的问题。果然指针就是指针,有的时候真的挺好用的。