天梯模拟--约瑟夫问题(7-18 猴子选大王 (20 分))

约瑟夫问题(有时也称为约瑟夫斯置换,是一个出现在计算机科学和数学中的问题。在计算机编程的算法中,类似问题又称为约瑟夫环。又称“丢手绢问题”.)据说著名犹太历史学家 Josephus有过以下的故事:在罗马人占领乔塔帕特后,39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止。然而Josephus 和他的朋友并不想遵从。首先从一个人开始,越过k-2个人(因为第一个人已经被越过),并杀掉第k个人。接着,再越过k-1个人,并杀掉第k个人。这个过程沿着圆圈一直进行,直到最终只剩下一个人留下,这个人就可以继续活着。问题是,给定了和,一开始要站在什么地方才能避免被处决?Josephus要他的朋友先假装遵从,他将朋友与自己安排在第16个与第31个位置,于是逃过了这场死亡游戏。       以上来自百度百科

 

约瑟夫问题是个很有名的问题:N个人围成一个圈,从第一个人开始报数,第M个人会被杀掉,最后一个人则为幸存者,其余人都将被杀掉。例如N=6,M=5,被杀掉的顺序是:5,4,6,2,3,1。

题目:

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

输入格式:

输入在一行中给一个正整数N(≤1000)。

输出格式:

在一行中输出当选猴王的编号。

输入样例:

11

输出样例:

7

20分的题最后只拿了17分,共4个测试点,有1个没过,过段时间再回头来找找原因,现附上队友20分的满分解答(要学习她的写代码的简洁明了,

有些可以省去{}的地方就要省去,

尤其要利用好while后()的作用,与答案变量相结合。

其次,要注意判断顺序的问题!!!

#include <bits/stdc++.h>//万能头文件 
using namespace std;
int main()
{
	int n,top = 0,count = 0,s = 0;//top用于标记每轮循环猴子的位置 ,count用于标记报数,s用于记录被淘汰的猴子的个数 
	int a[1005] ={0};
	cin >> n;
	while(s != n-1)//先决条件,即此种做法不用再将N=1的情况单列出来 
	{
		top++;
		if(top > n) top = 1;//先令top自加,若超出位置,说明要进行下一轮循环 
		if(a[top] == 0) count++;
		if(count == 3) 
		{
			a[top] = 1;
			count = 0;//当循环到3时,说明要再次从1开始报数 
			s++;
		}
	}
	for(int i = 1;i <= n;i++)
	{
		if(a[i] == 0) cout << i;
	}
	
}

 

 

然后是17分的答案

#include <stdio.h>
#include <iostream>
using namespace std;
int main()
{
	int N,cnt=0,t,ans;
	cin >> N;
	int mark[1005]={0};//mark数组作为标记,未被踢出的标记为0
	t=1; 
	if(N!=1)
	{
		for(int i=1;;i++)
	{
		if(mark[t]!=0)
		{
			i--;
		}//若被踢出,直接跳过 
		
		if(i%3==0&&mark[t]==0)
		{
			mark[t]=1;
			cnt++;
		}//每当轮到3的倍数,说明该报3了 
	
		t++;
		if (t==N+1)
		{
			t=1;
		}//开始新一轮循环 
		if(cnt==N-1)
		{
			break;
		}
		
		for(int i=1;i<=N;i++)
		{
			if(mark[i]==0)
			{
				ans=i;
			}
		}//寻找剩余的那只猴子 
	}
	cout<<ans;
	}
	else
	{
		cout << "1";
	}//我这种方法要单独讨论1是因为,我是先剔除再判断是否满足cnt==N-1
}

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值