C#试玩程序设计试题——数字的游戏(约瑟夫斯置换)

题目链接:
https://wenku.baidu.com/view/d8253e24f90f76c660371ac2.html?from=search
问题描述:
N个教徒和N个非教徒在深海上遇险,必须将一半的人投入海中, 其余的人才能幸免于难,于是他们想了一个办法: 2N个人围成一圈,从第一个人开始依次循环报数,每数到第9个人就将他扔进大海,如此循环直到只剩下N个人为止。问怎样的站法,才能使得每次投入大海的都是非教徒。
输入:
输入文件由一行构成,就是N的值
输出:
输出文件是一行字符串,字符串由N个@字符(代表教徒)和N个+字符(代表非教徒)排列组成。该排列使得按照提述方法每次投入大海的都是非教徒。
输入样本:
15
输出样本:
@@@@+++++@@+@@@+@++@@+++@++@@+

思路

假设队里这里有2N个教徒,扔出去的“变成”非教徒,就是数到9的那个“变成”非教徒,变过的人再数到的就跳过,因为这个人已经扔出队伍了;话说这道题真的很有意思~
这里N值就不改成输入式获取了,有爱自改;

思路1:边数边翻牌子

List容器

			int n = 15;
            Console.WriteLine("N:"+ n);
            List<int> normal = new List<int>();// 校验用
            List<string> list = new List<string>();
            for (int l = 0; l < 2*n; l++)// 添加所有都是教徒的队伍
            {
                list.Add("@");
            }

            for (int normalCount = 0,k = 1,i = 1; normalCount < n; k++)
            {
                if (k >= 2 * n)// 保证索引循环
                {
                    k = 0;
                }

                if (list[k] == "@")// 这里数到教徒才计数+1并进行替换,因为替换过的都变成非教徒,非教徒替换后如果第二轮遇上时应该跳过,因为第一轮时已经被抽取出来,相当于是个空位
                {
                    i++;// 计数+1
                    if (i % 9 == 0)// 9的倍数时将原来的教徒换成非教徒
                    {
                        list[k] = "+";
                        normal.Add(k + 1);// 校验用
                        normalCount++;// 非教徒+1
                    }
                }
            }

            foreach (var item in list)
            {
                Console.Write(item);
            }
            Console.WriteLine();
            normal.Sort();
            foreach (var item in normal)// 显示剔除序号(=索引+1)
            {
                Console.Write(item+"\t");
            }
            Console.WriteLine();
            //Console.WriteLine("校验:\n@@@@+++++@@+@@@+@++@@+++@++@@+");

            Console.WriteLine("取出的成员:");
            // 模拟抽取过程校验
            for (int getOutCount = 0, i = 1; getOutCount < n; i++)
            {
                if (i == 9)
                {
                    if (i > list.Count) 
                    {
                        i %= list.Count;
                    }
                    Console.Write(list[i - 1]);// 即将取出的人
                    list.RemoveAt(i - 1);// 取出
                    getOutCount++;// 取出人数+1

                    // 下面把数过的人放到队尾组成新的队伍给下次循环数
                    List<string> fontList = new List<string>();
                    fontList.AddRange(list.GetRange(0, i-1));
                    list.RemoveRange(0, i-1);
                    list.AddRange(fontList);
                    i = 1;// 重新数9个
                }
            }

            Console.ReadKey();

Queue容器

			int n = 15;
            Console.WriteLine("N:" + n);
            Queue<Dictionary<int,char>> queue = new Queue<Dictionary<int, char>>();
            for (int i = 1; i <= 2*n; i++)
            {
                queue.Enqueue(new Dictionary<int, char>{ { i, '@' } });
            }

            int delCount = 0;// 非教徒数

            while (delCount < n)
            {
                for (int j = 0; j < 9; j++)
                {
                    Dictionary<int, char>  man = queue.Dequeue();
                    int key = man.Keys.First();
                    char value = man.Values.First();

                    if (value == '+')
                    {
                        j--;// 这个已经是脱离队伍的,所以索引回退
                    }
                    else if (j == 9 - 1)
                    {
                        value = '+';
                        delCount++;
                    }
                    queue.Enqueue(new Dictionary<int, char> { { key, value } });
                }
            }

            while (queue.Peek().Keys.First() != 1) // 还原顺序
            {
                queue.Enqueue(queue.Dequeue());
            }

            foreach (var item in queue)
            {
                Console.Write(item.Values.First());
            }
            Console.WriteLine();

思路2:模拟【业务】操作

直接还原情景模拟抽取操作,操作完后按原来序号排序

			int n = 5;
            Console.WriteLine("N:" + n);
            Queue<Dictionary<int,char>> queue = new Queue<Dictionary<int, char>>();
            for (int i = 1; i <= 2 * n; i++)
            {
                queue.Enqueue(new Dictionary<int, char> { { i, '@' } });
            }

            SortedDictionary<int, char> resultList = new SortedDictionary<int, char>();// 结果队列
            while (queue.Count > n)
            {
                for (int j = 0; j < 9; j++)
                {
                    Dictionary<int, char> men = queue.Dequeue();
                    int key = men.Keys.First();
                    char value = men.Values.First();

                    if (j != 9 - 1)
                    {
                        queue.Enqueue(men);
                    }
                    else 
                    {
                        value = '+';
                    }

                    if (resultList.ContainsKey(key))
                    {
                        resultList[key] = value;
                    }
                    else 
                    {
                        resultList.Add(key, value);
                    }
                }
            }

            foreach (var item in resultList)
            {
                Console.Write(item.Value);
            }
            Console.WriteLine();
            
            Console.ReadKey();

结果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值