zcmu 5022: 约瑟夫

题目链接: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;
}

链表很轻松的帮我解决了收尾相连与去除中间元素的问题。果然指针就是指针,有的时候真的挺好用的。

猜你喜欢

转载自blog.csdn.net/eatkeyborad/article/details/115030247