报数模拟。
有n 个人围成一个圈,从1到n 按顺序排好号。然后从第一个人开始顺时针 报数(从1到3报数) ,报到3的人退出圈子后,后面的人继续从1到3报 数,直到留下最后一个人游戏结束,问最后留下的是原来第几号。
输入描述:输入一个正整数n(4<n<600)
输出描述:输出最后留下的人,原来的编号是多少?
【样例输入】
5
【样例输出】
4
//蓝桥杯C++题目《报数模拟》创氪编程参考程序 之 队列解法
#include <bits/stdc++.h>
using namespace std;
int main(){
int n;//定义变量
cin >> n;//输入变量值
queue<int> q;//队列(Queue)代表了一个先进先出的对象集合
for (int i = 1; i <= n; ++i){
q.push(i);
}
int cnt = 0;
while (q.size() > 1){
cnt++;
if (cnt % 3 != 0){
int x = q.front();
q.push(x);
}
q.pop();
}
cout << q.front() << endl;
return 0;
}
【算法分析】
本题可以采用建立标志位的方法求解,但如果使用循环链的思想,则解题效率更高。n个人围成一圈,把一个人看成一个节点,n个人采用链接方式,即每一个节点有一个前继节点和后继节点,每一个节点有一个指针指向下一个节点,最后一个节点的指针指向第一个节点。这就是单链循环的数据结构。当m个人出列时,将m的前继节点指针指向m节点的后继指针节点,即把m节点驱出循环链。
1.建立循环链表
当用数组实现本体链式结构时,数组a【i】作为“指针”变量来使用,a[i]存放下一个节点的位置。
设立指针j指向当前节点,则移动节点过程为j=a[i],当数到m时,m节点出链,则a[j]=a[a[j]]。
2.设立指针,指向当前节点,设立计数器,计数数到多少人。
3.沿链移动指针,每移动一个节点,计数器的值加一,当计数器的值为m时,则m节点出链,计数器的值置为1.
4.重复3,直到n个节点出链为止。
//蓝桥杯C++题目《报数模拟》创氪编程参考程序 之 数组解法
#include<bits/stdc++.h>
using namespace std;
int main()
{
int i, j = 0, k = 0, n;
int a[30] = {0};//数组多大最大 N的上限
scanf("%d", &n);//输入有几个人玩游戏
for (i=0; i<n; i++)
{
a[i] = 1;//1代表活着,0代表出局
}
for (i=1; i<4; i=i%3+1)//控制i的值在[0,3]
{
if (3==i && a[j]!=0)
{
a[j] = 0;
k++;
if (n-1 == k)
break;
j = (j+1)%n;
continue;
}
if (0 == a[j])
{
j = (j+1)%n;
i--;
continue;
}
j = (j+1)%n;
}
for (i=0; i<n; i++)
{
if (1 == a[i])
printf("%d", i+1);
}
}