这里是生物专业的小希,初次见面请多多指教 > <
去年在好朋友的怂恿下稀里糊涂地报名了蓝桥杯,没想到一直拖到寒假才开始学习(真是惭愧)
目前的学习进度是完成了C++的基础知识,(在B站上面学的),真的非常基础,核心编程那块还没有开始,所以做题的方法十分有限 😦
下面有请大家欣赏第一道让我一做就是一天的题~
约瑟夫环
简单版
有n人围成一圈,顺序排号。从第1个人开始报数(从1到3报数),凡报到3的人退出圈子,问最后留下的是原来的第几号的那位。
初步思路:一点都没有。讨教了初中二年级的弟弟之后,由衷地敬佩,真不愧是我弟弟。
解题思路:
- 创建一个很长的数组。
- 将里面的前n个元素赋值 1。
1 1 1 1 1 1 1
- 设置“报数”参数 m=0,“退出”参数 a=n。
- 开始循环,若遇到 1,则“报数”参数 m++。
- 若 m 是3的倍数,则将此数组元素赋值 0,同时“退出”参数 a–。
1 1 0 1 1 0 1
- 一轮循环走完后,再从第一个元素开始第二轮循环,直到 a=1,此时数组里面只有一个元素的值为 1。
0 0 0 1 0 0 0
- 新建一个循环,找到值为1的元素下标,得到答案。
该思路的优点:让小白觉得耳目一新的地方是“报数”参数 m 的设置,比起绞尽脑汁地去想,怎么让元素退出(不再参与报数)呢,不如让它留在数组内,通过 m 阻止它“报数”。
易错点:后期报数时一定会有两个值为 0 的元素连续出现的情况,这个时候虽然 m 的值并没有变化,但很有可能导致 a– 运行多次(如果此时刚好m为3的倍数),因此需要在 a– 之前加一个判断语句(具体参照代码如下哦)
我的答案:
#include<iostream>
using namespace std;
int main()
{
int n,m=0,i,j;
cin>>n;
int a=n,arr[1000];
for(i=0;i<n;i++) arr[i]=1;
for(i=0;i<n;)
{
if(arr[i]==1) m++;
if(m%3==0)
{
if(arr[i]==1) a--;
arr[i]=0;
}
if(b==1)
{
for(j=0;j<n;j++)
{
if(arr[j]==1)
{
cout<<j+1;
break;
}
}
break;
}
i++;
if(i==n) i=0;
}
return 0;
}
后来在网上找其他人的算法的时候还看到了用链表(这个还没学嘿嘿)和递归的办法,递归法写出来的代码只有短短几行,好的!等我脑子清楚的时候把它搞懂,再回来交作业!