1748:约瑟夫问题

题目

总时间限制: 1000ms 内存限制: 65536kB

描述

约瑟夫问题:有n只猴子,按顺时针方向围成一圈选大王(编号从1到n),从第1号开始报数,一直数到m,数到m的猴子退出圈外,剩下的猴子再接着从1开始报数。就这样,直到圈内只剩下一只猴子时,这个猴子就是猴王,编程求输入n,m后,输出最后猴王的编号。

输入

每行是用空格分开的两个整数,第一个是 n, 第二个是 m ( 0 < m,n <=300)。最后一行是:

0 0

输出

对于每行输入数据(最后一行除外),输出数据也是一行,即最后猴王的编号

样例输入

6 2
12 4
8 3
0 0

样例输出

5
1
7

题意

有n只猴子围成一圈,顺时针从第1号开始报数,数到m的猴子退出,输入n和m,输出最后一只猴子的编号。

思路

创建一个包含n个点的循环链表,再通过指针遍历链表,数到m时就将当前节点从链表中删除,一直重复这个过程直到链表中只剩下一个节点,这个节点的编号就是猴王的编号。

代码

#include<bits/stdc++.h>
using namespace std;
int n,m;
//定义链表
struct p{
    int num;//猴子的编号
    p *next;//指向下一个节点的指针
    p(){
        next=NULL;//初始化next为空
    }
};
void f(int n,int m){
    //创建头节点
    p *h=new p();
    h->num=1;
    h->next=NULL;
    p *tmp=h;//用于遍历链表
    
    //创建剩余的n-1个节点
    for(int i=1;i<n;i++){
        p *t=new p();//创建新节点
        t->num=i+1;//设置编号
        tmp->next=t;//连接新节点到链表末尾
        tmp=tmp->next;//移动tmp到新节点
    }
    tmp->next=h;//将链表首尾相连,形成循环
	//直到只剩一个节点时停止
    while(tmp->next!=tmp){//当节点的next指向自己时,说明只剩一个节点
        //移动m-1次
        for(int i=1;i<m;i++){
            tmp=tmp->next;//指向下一个节点
        }
		//将tmp的next指向下下个节点,跳过第m个节点(删除)
        tmp->next=tmp->next->next;
    }
    //输出最后剩下的猴王编号
    cout<<tmp->num<<endl;
}

int main(){
    //循环输入,直到遇到0 0
    while(cin>>n>>m){
        if(n==0&&m==0) break;//输入0 0时结束程序
        f(n,m); //调用函数
    }
    return 0;
}
posted @ 2025-09-27 18:35  骁翊  阅读(52)  评论(0)    收藏  举报