Josephus问题

此代码解决是Josephus问题的变种,即n个数中,第m个数出列组成新数组,直到数组中只剩一个数,则此数为结果。

#include <iostream>
using std::cin;
using std::cout;
using std::endl;

//josephus

/*
解题思路:
    _len长度的元素值从1~_len的数组,每(_space+1)个数组成一组,丢弃前_space个数并留下第_space+1个数。
若_len长度非(_space+1)整数倍,则剩余的元素保存于数组首(不会覆盖掉第一个待保存的数),其余元素依次处理
,保留下的数紧挨着存放,最终组成一个更小的数组(原数组的约1/3)。
    一直处理数组直到数组的有效长度len小于等于_space,此时整个数组无法再通过之前的方法获取待保留的数,
因此进行特殊处理。最终获取结果。
*/

void josephus(int *_arr, int _len, int _space){

    //特殊情况
    if(_space<1){
        cout<<"问题无解!"<<endl;
        return;
    }
    else if(_space>_len){
        cout<<"结果:"<<_arr[_space%_len]<<endl;
        return;
    }

    int space=0;        //间隔计数
    int len=_len;       //数组有效长度

    //数组有效长度大于_space,则可直接通过循环数组获取待保留的数
    while(len>_space){
        int index=0;                //标示待保留的数保存的位置
        int left=len%(_space+1);    //不能组成(_space+1)对的剩余数个数

        if(left!=0){
            for(int i=0;i<left;i++){
                _arr[i]=_arr[len-left+i];
            }
            index+=left;
            space+=left;
        }

        for(int i=left;i!=len;i++){
            if(space!=_space)
                space++;
            else{
                _arr[index++]=_arr[i];
                space=0;
            }
        }
        len=index;          //index标示有效数组长度
    }

    //剩余有效数组不能组合成一个(_space+1)对,因此特殊处理
    if(len==1) cout<<"结果:"<<_arr[0]<<endl;
    else {
        int index=0;
        space=0;
        while(space!=_space){
            space++;
            index++;
            if(index==len) index=0;
        }
        cout<<"结果:"<<_arr[index]<<endl;
    }
}

//main
int main(){
    int len=0;
    int space=0;

    cout << "==========Josephus==========" << endl;
    cout<<"数字个数:";
    cin>>len;
    cout<<"循环间隔:";
    cin>>space;

    int* _arr=new int[len];
    for(int i=0;i<len;i++)
        _arr[i]=i+1;
    josephus(_arr,len,space);
    cout<<endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值