Joseph约瑟夫问题(C++)

题目描述

The Joseph's problem is notoriously known. For those who are not familiar with the original problem: from among n people, numbered 1, 2, . . ., n, standing in circle every mth is going to be executed and only the life of the last remaining person will be saved. Joseph was smart enough to choose the position of the last remaining person, thus saving his life to give us the message about the incident. For example when n = 6 and m = 5 then the people will be executed in the order 5, 4, 6, 2, 3 and 1 will be saved. 

Suppose that there are k good guys and k bad guys. In the circle the first k are good guys and the last k bad guys. You have to determine such minimal m that all the bad guys will be executed before the first good guy.

输入

The input file consists of separate lines containing k. The last line in the input file contains 0. You can suppose that 0 < k < 14.

输出

The output file will consist of separate lines containing m corresponding to k in the input file

样例输入

3
4
0

样例输出

5
30

题目描述


约瑟夫的问题是众所周知的。对于那些不熟悉原始问题的人:从 n 个人中,编号为 1、2、. . ., n, 围成一圈,每隔 m 个人就会被处决,只有最后一个人的生命会被拯救。约瑟夫很聪明地选择了最后一个人的位置,从而挽救了他的生命,向我们传达了有关事件的信息。例如,当 n = 6 和 m = 5 时,人将按 5、4、6、2、3 和 1 的顺序被处决

假设有 k 个好人和 k 个坏人。在圆圈中,前 k 个是好人,最后 k 个是坏人。您必须确定最小的 m,以使所有坏人都将在第一个好人之前被处决。

输入

输入文件由包含 k 的单独行组成。输入文件的最后一行包含 0。您可以假设 0 < k < 14。

输出

输出文件将由包含 m 的单独行组成,对应于输入文件中的 k

样例输入

3
4
0

样例输出

5
30

约瑟夫问题,题目要求给出一个数值k,其实总人数编号为2* k, 那么需要在0 - k编号出列之前必须让所有[k, 2 * k]编号的人出列,需要找到这个循环数来让人出列。暴力求解,让m从k开始递增(若m小于k,第一次出列必定是好人),对出列的数值进行判断,如果有出现出列数值小于k,重新开始循环

#include <iostream>
using namespace std;
int main()
{
	int k, m,j;
	int s; //s为每次删除的位置
	int n; //n为总人数,即2k
	//因为k<14,所以m的所有可能取值就是14到28一共十四个数字
	int a[14] = { 0 };   //数组a用来存储k(1到13)对应的m
	while (1)
	{
		cin >> k;
		if (k == 0)
		{
			break;
		}
		m = k; //m从k开始递增
		n = 2 * k;
		if (a[k] == 0)  //即这个k还没有对应的m
		{
			while (1)
			{
				s = 0;
				for (j = 0; j < k; j++)
				{
					s = (s + m - 1) % (n-j);  //这是每次删除的位置
					if (s < k)  //杀了好人,不合规矩
					{
						break;
					}
				}
				if (j == k) break;
				m++;
			}
			a[k] = m;
		}
		cout << a[k] << endl;
	}
	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值