C语言解约瑟夫环问题(随机密码版)

本文将用数组求解约瑟夫环问题。

题目描述

编号为1,2,3,……n的n个人按顺时针方向围坐一圈,每人持有一个密码(正整数)。一开始任选一个正整数作为报数上限值m,从第一个人开始按顺时针方向自1开始顺序报数,报到m时停止报数。报m的人出列,将他的密码作为新的m的值,从他在顺时针方向上的下一个人开始重新从1报数,如此下去,直至所有的人全部出列为止。试设计一个程序求出所有人出列的顺序。

输入格式

输入人数 n

输出格式

输出每个人的随机密码和初始密码,随后按顺序输出出列的号码及其密码。

输入输出样例

说明/提示

初始的10人和密码的随机大小都可更改,为了方便测试才设置初始值为10的。

解题思路:

创建一个大小为n的数组用来表示n个人,同时将此元素的第一和第二个域分别存放密码和下一个人的序号。同时使用计数器变量来计算报数的数字和判断是否出列。每出列一人将会把出列前一个人的next域改变,报数会跳过已出列的号码。

代码实现:

#include<iostream>
#include<iomanip>
#include<stdlib.h>
#include<time.h>
using namespace std;
int random();
int main()
{   /*Num数组的10个元素分别代表一个人的号码,元素的第一个域存放每个人的密码,第二个域存放下一个人的序号*/
    /*Count为计数器,Alive为活着的人数*/
    /*Pre是上一个报数的人的序号,Now是当前报数人的序号*/
    int Num[10][2], Count = 0, Alive = 10, Pre = 0, Now, i, Password;
    srand((unsigned)time(0)); /*设置随机数种子为时间*/
    cout << "  请输入人数(最多10人):";
    cin >> Alive;
    if (Alive > 10 || Alive == 0)
    {
        /*判定人数是否超过上限*/
        for (; Alive > 10 || Alive == 0;)
        {
            /*若超过上限则重新输入*/
            cout << "  输入错误!";
            cout << "  请重新输入人数(最多10人):";
            cin >> Alive;
        }
    }
    for (i = 0; i < Alive; i++)
        Num[i][1] = (i + 1) % Alive;    /*初始化next域*/
    Password = random();    /*生成初始密码*/
    for (i = 0; i < Alive; i++)
    {
        /*为每个号码随机分配密码*/
        Num[i][0] = random();
        if (Num[i][0] == Num[i - 1][0])
        {
            /*检查相邻号码的密码没有重复*/
            for (; Num[i][0] == Num[i - 1][0];)
                Num[i][0] = random();
        }
        cout << "  " << i + 1 << "号的密码为『" << Num[i][0] << "』" << endl;
    }

    cout << "-------------推算开始-------------" << endl;
    cout << "         初始密码为『" << Password << "』!" << endl;
    cout << endl;

    /*开始推算约瑟夫环的出列顺序*/
    for (Now = 0; Alive != 0; Now = Num[Now][1])
    {
        Count++;    /*报数加一*/
        if (Count == Password)
        {
            Alive--;       /*存活人数减一*/
            Password = Num[Now][0];   /*更改报数上限*/
            Num[Pre][1] = Num[Now][1]; /*前一个人的next域改变*/
            cout << "      " << Now + 1 << "号玩家报出了号码『" << Count << "』!" << endl;
            cout << "          " << Now + 1 << "号玩家已出列!" << endl;;//输出这一次出列的人的编号
            if (Alive == 0)
            {
                cout << "-------------推算结束-------------" << endl;
            }
            else
            {
                cout << "        " << "下一个密码是『" << Num[Now][0] << "』!" << endl;
            }
            cout << endl;
            Count = 0;       /*报数归零*/
        }
        else
        {
            Pre = Now;       /*上一个报数的序号改变*/
        }
    }
}
int random()
{   //生成随机数
    int a;
    a = rand() % 100 + 1;
    return a;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值