猴子选大王(约瑟夫问题)的实现方法

问题描述

一群猴子要选新猴王。新猴王的选择方法是:让N只候选猴子围成一圈,从某位置起顺序编号为1~N号。从第1号开始报数,每轮从1报到3,凡报到3的猴子即退出圈子,接着又从紧邻的下一只猴子开始同样的报数。如此不断循环,最后剩下的一只猴子就选为猴王。请问是原来第几号猴子当选猴王?
输入格式:
输入在一行中给一个正整数N(≤1000)。
输出格式:
在一行中输出当选猴王的编号。

输入样例:

11

输出样例:

7

数组模拟
使用标记法也就是数组模拟的方法,我自己起的名字哈哈。简单易懂使用一个mark数组来表示当前的这只猴子有没有数过最后一个数字(初始值均为0,表示没有数过,数过的赋值1),记录每一次循环位于队尾的猴子数的数字,合理给第一只猴子数的数赋值。
代码如下:

#include <iostream>
#include <stdio.h>
using namespace std;
// 0 1 2 3 4 5 6 7 8 9 10
int main()
{
    bool mark[1001] = {0};//动态标记 未被选中过0 选中过1
    int N = 0;//输入的猴子数
    scanf("%d",&N);
    int num = N;
    //int currentNum = 1;//从1开始遍历
    int cunt = 1;
    while(num > 1){
        for(int i = 0;i < N;++i){
            bool selecting = 0;
            //判断当前的猴子是没有被剔除圈的,才有资格报数
            if(mark[i] ==0){
                selecting = 1;
            }
            //选中的猴子 数到三的猴子
            if(selecting&&(cunt == 3)){
                mark[i]=1;
                --num;
            }
            //数到最后的猴子
            if(selecting){
                if(cunt==3)
                    cunt=1;
                else
                    ++cunt;
            //cunt = (++cunt)%3;
            }
        }
    }
    for(int j = 0;j < N;++j){
        if(!mark[j]){
            //printf("选出的猴子大王编号是%d",j+1);
            printf("%d",j+1);
            break;
        }
    }
    return 0;
}


原本写的比较简单,再补充一个vector版的

vector数组实现

/*****************************
* effect:vector版猴子选大王
* author:wyrctzy
* environment:Code::Blocks 16.01
* time:2019/1/25 00:00
*****************************/
#include<iostream>
#include<vector>
using namespace std;
int main()
{
	int N;
	vector<int>monkey;//选择序列
	vector<int>::iterator item;//遍历指针
    cin>>N;
	for(int i=1;i<=N;i++)
        monkey.push_back(i);//在vector尾部把当前的i值追加上
	item=monkey.begin();
	//剩下的最后一个就是king
	while(monkey.size()>1)
	{
		for(int i=1;i<3;i++)
		{
			item++;
			//到达vector尾部,重新从头开始
			if(item==monkey.end())
                item=monkey.begin();
		}
		//数3的直接从数组中删掉
		item=monkey.erase(item);
		//判断一下删除完成后指针的情况,是不是指在队尾
		if(item==monkey.end())
            item=monkey.begin();
	}
	//输出指针当前位置的值
	cout<<*item<<endl;
	return 0;
}

数组的基本就是这样了,还可以使用数学上的方法解决该问题。


先看一下约瑟夫问题的百度百科给出的相关解释
什么是约瑟夫问题–百度百科
数学方法解决

递推公式:
f[1]=0;
f[i]=(f[i-1]+m) mod i; (i>1)

代码如下:

#include <iostream>
using namespace std;
const int m = 3;
int main()
{
    int n, f = 0;
    cin >> n;
    for (int i = 1; i <= n; i++)
    	f = (f + m) % i;
    cout << f + 1 << endl;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值