模拟训练:约瑟夫问题(链表模拟)

解题思路:本题可以使用链表模拟猴子报数,这一方法具有较高的效率并且易于理解。大致方法是构成一个链表环,表头指针跟着计数值共同变化,等计数值等于报数值时进行删除操作。但是用链表做题一定要注意题目有一特殊情况,即m==1时,因为链表中的判断及处理都是在前一个节点进行,因而m==1是该方法的一处死角,一定要做特殊化的处理!其次,链表的使用中有不少的细节需要我们留意,可以关注一下代码中的注释部分。

总时间限制: 

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
#include<stdio.h>
struct Monkey
{
	int ID;
	Monkey *next;
};
int main()
{
	Monkey *link,*tail,*monkey;
	int n,stride,count;
	while(scanf("%d%d",&n,&stride)!=EOF)
	{
		if(n==0&&stride==0)
		break;
		if(stride==1)                        //链表做这题一定要考虑这种情况,算是个大坑! 
		{
			printf("%d\n",n);
		    continue;
		}
		link=tail=NULL;
		for(int i=1;i<=n;i++)
		{
			monkey=new Monkey;
			monkey->ID=i;
			if(tail==NULL)
			{
				link=tail=monkey;
			}
			else
			{
				tail->next=monkey;           //此处设置正确的指针指向。 
				tail=monkey;
			}
		}
		tail->next=link;
		count=1;
		while(link!=NULL)
		{
			if(link->next==link)
			{
				printf("%d\n",link->ID);
				delete link;                //删除最后一处链表空间。 
				break;
			}
			if(count==stride-1)             //这里一定要注意,因为使用的是链表格式,所以这里的count数数为stride-1时就要停下进行处理,因为必须在前一个节点进行处理! 
			{
				monkey=link->next;
				link->next=monkey->next;    //这一句将该节点从链表中删除。 
				//printf("%d ",monkey->ID);
				delete monkey;              //使用链表一定要删除相应的空间。 
				count=0;
			}
			count++;
			link=link->next;
		}
	}
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值