问题 : [出圈]
题目描述
设有n个人围坐一圈并按顺时针方向从1到n编号,从第1个人开始进行1到m的报数,报数到第个m人,此人出圈,再从他的下一个人重新开始1到m的报数,如此进行下去直到所剩下一人为止。
输入
输入多行,每行2个数,分别表示n和m.
输出
计算每一行中最后剩下这个人的编号.
样例输入
10 3
样例输出
4
可以通过两种方法实现:
第一种:数组
方法:
数组中某处等零,即代表出圈(a[4]=0,即代表4的位置出圈)
先设一个数组a[1000]存放将要循环的数据n,然后设x用来判断出圈了几个数(当x=n-1即结束,仅剩一人未出圈)
再设i,y来不断循环,
i用来判断每一次循环到第几个数,当i=m即表示报一次数,位于m的人出圈(数组中此处归零),i归零,重新报数。
y用来表示数组中对应i的位置,当y=n+1时,表示全部人循环一次,y归零。
注意的地方:
当全部人循环一遍过后,数组中某些地方归零,所以当y到此处时进行判断,当a[y]=0时,y++(此处用while循环判断,直到a[y]不等于零);
代码:
#include<iostream>
using namespace std;
int main()
{
int n, m;
while (scanf("%d%d", &n, &m) == 2)
{
int a[1000];
for (int i = 1; i <= n; i++)
{
a[i] = i;
}
int x = 0;
int i = 1;
int y = 1;
while (x != n - 1)
{
if (i == m)
{
while (a[y] == 0)
{
y++;
if (y == n + 1)
{
y = 1;
}
}
a[y] = 0;
x++;
i = 0;
}
i++;
y++;
if (y == n + 1)
{
y = 1;
}
if (a[y] == 0)
{
while (a[y] == 0)
{
y++;
if (y == n + 1)
{
y = 1;
}
}
}
}
cout << a[y]<<endl;
}
getchar();
getchar();
}
第二种:循环链表
方法:
比数组要简单,先将需要循环的数存到链表中,然后进行循环。
定义一个i值,每次i=m时,此节点删除,然后直到仅剩一个结点,即为所求值。
代码:
#include<iostream>
using namespace std;
struct Node
{
int data;
Node *next;
};
int main()
{
int n, m;
while (scanf("%d%d", &n, &m) == 2)
{
Node *head = new Node;
head->data = 1;
Node *p = new Node;
p = head;
for (int i = 2; i <= n; i++)
{
Node *q = new Node;
q->data = i;
p->next = q;
p = q;
}
p->next = head;
int i = 1;
Node *w = new Node;
w = head;
while (head != head->next)
{
if (i+1 == m)
{
w = head->next;
head->next = w->next;
head = head->next;
i = 1;
}
else
{
head = head->next;
i++;
}
}
cout << head->data<<endl;
}
}