2020.3.1更新
错误理解题目的意思,以为的是每过一轮就要重新排列(导致编号为1的人永远出不去),其实是每出局一个人就自动变成新的圈,然后循环报数。
不过问题不大,只要把每次判断当前未出局人数前的num清零操作取消即可。
首先想说的是确实是已经好久没写博客了,还是自己太懒…和自己感觉没啥特别想写的,所以开学以后学了c#,顺便写一点算法相关的问题吧。
【问题描述】
n 个人围成一圈, 并依次编号1~n。从编号为1 的人开始,按顺时针方向每隔一人选出一个,剩下的人重新围成一圈,如此循环直到剩下两人,这剩下的两人就是幸运儿。如果你想成为最后两个幸运儿,请问开始时应该站在什么位置?(设3<=n<=50)
【输入】
开始时的人数n
【输出】
第1 行是选出顺序,第2 行是两名幸运儿的开始位置(按升序排列),位置编号之间用一个空格分开。
【样例输入】
12
【样例输出】
2 4 6 8 10 12 3 7 11 5
1 9
思考:一开始拿到这个题的时候,确实没啥好的想法,然后百度了一波,发现这是约瑟夫环问题,然后看了一些大佬写的代码,讲道理没有特别看懂,然后索性不看了,自己想了想以后好像可以用数组的方法去解决问题。
首先定义一个数组,代表人数,初始值都为false,由于最后只能留下两个人,所以当还没出局的人数大于2时,一直进行循环。
定义一个变量num来存储实际已经间隔的人数,每个人“报数”时num都会加一,当遇到该位置为之前已经出局的人时,将num减一,当num为2时,即代表该位置的人要出局,再将num置为0即可,下面是代码。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
| using System; using System.Collections.Generic; using System.Linq; using System.Text;
namespace Week2 { class Problem3 { static void Main(string[] args) { Console.Write("请输入人数:"); int n = Convert.ToInt32(Console.ReadLine()) ;
//初始化 bool[] People = new bool[n + 1];
for(int i = 0; i < n + 1; i++) { People[i] = false; }
int now_count = n; //当前存在人数 int num = 0; //判断间隔的人数 while(now_count > 2) { for (int j = 1; j < n + 1; j++) { num++; if(People[j] == true) { num -= 1; //当前的人之前已经出局了 } else if(num == 2) { People[j] = true; Console.Write(j + " "); now_count -= 1; num = 0; } } }
Console.WriteLine();
for(int i = 1; i < n + 1; i++) { if(People[i] == false) { Console.Write(i + " "); } }
Console.ReadKey();
} } }
|