Welcome To ZCMU Online Judge

                                                                                不忘初心,砥砺前行!

1474: 小孩报数问题

Time Limit: 1 Sec  Memory Limit: 128 MB
Submit: 473  Solved: 213
[Submit][Status][Web Board]

Description

  有N个小孩围成一圈,给他们从1开始依次编号,现指定从第W个开始报数,报到第S个时,该小孩出列,然后从下一个小孩开始报数,仍是报到S个出列,如此重复下去,直到所有的小孩都出列(总人数不足S个时将循环报数),求小孩出列的顺序。

Input

每组测试数据有3个正整数,小孩的人数N(N<=64),W,S (W < N)。

Output

输出小孩出列的顺序。

Sample Input

5 2 3

Sample Output

4

2

1

3

5

题解:

其实这题就是著名的约瑟夫环问题。

这里用了两种做法

/*
循环链表做法
PS:准确来说做这题完全不需要这样,可是如果用循环链表写出这题了,我觉得链表这块可以说入门了,看不懂的可以试着自己画个图
PPS:最下方借鉴了另一位同学更为简单的数组的做法
*/
#include <bits/stdc++.h>
using namespace std;
typedef struct child      //定义一个child节点
{
	int bianhao;
	struct child *next;
};
int main()
{
	int n, w, s;
	while (~scanf("%d", &n))
	{
		scanf("%d%d", &w, &s);
		child *head = NULL, *pc, *p;
		head = (child *)malloc(sizeof(child));
		head->next = NULL;
		pc = head;								//处理一下链表头节点head,和用来移动的指针pc
		for (int i = 1; i <= n; i++)			//生成一条含有n个节点的链表
		{
			p = (child *)malloc(sizeof(child));	//申请一个child节点
			p->bianhao = i;						//给每个节点编号
			pc->next = p;						//接上一个节点
			p->next = NULL;						//保证最后一个节点的next为空
			pc = p;								//移动的指针pc移到新生成的节点,为下一个节点做准备
		}
		pc->next = head->next;					//让最后生成的节点指向第一个节点,使这条链表成为一个环
		//pc = pc->next;
		w--;									//为什么要减一?下面说
		while (w)
		{
			pc = pc->next;						
			w--;
		}										//定位到【第W个开始报数】的前一个节点,即第W-1个节点
		int temp;
		while (n)								//n次循环过后所有人都能出列
												//这时候上面w--的作用就体现出来了
												//在不引入新的指针的情况下
												//(指针太多了会乱,所以这里开始我只用了pc来操作,当然了你是跟毛子一样强的大佬四级指针什么的请无视)
												//故意少算一个,即定位到要删除的节点的前面
												//这样才好删除我们不要的节点
		{
			if (1 == s)
			{
				temp = pc->next->bianhao;		//此时pc节点是我们要删除的节点的前一个,那么我们用temp存储要删除节点(即pc->next)的编号(->bianhao)
				pc->next = pc->next->next;		//此处就是删除操作,下同
												//此时pc是要删除节点的前一个,那么pc->next->next不就是要删除节点的下一个么
			}
			else
			{
				for (int i = 1; i < s; i++)
				{
					pc = pc->next;
					temp = pc->next->bianhao;
				}
				pc->next = pc->next->next;
			}
			printf("%d\n", temp);				//每次循环打印出被删除节点的编号
			n--;
		}
	}
	return 0;
}
/*数组做法*/#include<iostream>   
#include<stdio.h>
using namespace std; 
    int p[65];  
int main()  
{  
    int w,s,n,i;  
    while(cin>>n){
        for(i=0;i<n;i++)p[i]=i;  
        cin>>w>>s;  
        w=(w+n-1)%n;  
        do{  
           w=(w+s-1)%n;  
           printf("%d\n",p[w]+1);
           for(i=w;i<n-1;i++)  
           p[i]=p[i+1];  
        }while(--n);
    }
    return 0;  
}