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;
}