约瑟夫环问题

3 篇文章 0 订阅
1 篇文章 0 订阅

约瑟夫环(约瑟夫问题)是一个数学的应用问题:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。通常解决这类问题时我们把编号从0~n-1,最后结果+1即为原问题的解。

先给出一个通式:Y(1) = 0; Y(n) = (Y(n-1)+m)%n;

下面给出数学推导过程:

还未报数时编号为:0,1,2,...,n-1

第一次报数:

出列的人为:k = (m-1)%n;

此时的编号为:k,k+1,k+2,k+3,...,k-3,k-2

作如下变换:

k->0 (0+k)%n

k+1->1 (1+k)%n

k+2->2 (2+k)%n

k+3->3 (3+k)%n

...... ......

k-3->n-3 (n-3+k)%n

k-2->n-2 (n-2+k)%n

相当于把n个人的约瑟夫换问题转换为(n-1)个人的约瑟夫换问题,假设已经解出(n-1)个人的约瑟夫环问题的解为: Y(n-1),那么根据以上的映射原则: Y(n) = (Y(n-1)+k)%n==>

Y(n) = (Y(n-1) +m%n)%n ==> Y(n) = Y(n-1)%n +m%n%n ==> Y(n) = Y(n-1)%n +m%n ==> Y(n) = (Y(n-1) +m)%n

所以得到以下通式:

--------------------

Y(1) = 0

Y(n) = (Y(n-1) +m)%n (n>1)

--------------------

例如:要求10个人,报数为3出列,最后胜利者的编号。

public class YueSeFuHuanProblem
{

	public static void main(String[] args)
	{
		//假设有10个人,报到3出列,默认编号从0开始,如从一开始,结果加1即可。
		for (int i = 1; i < 11; i++)
		{
			System.out.println("第"+i+"次出列的人的编号为:"+yueSeFuHuan(10, 3, i));
			
		}
	}

	public static int yueSeFuHuan(int n,int m,int i)
	{
		if(i==1)
			return (m-1+n)%n;
		else
			return	(yueSeFuHuan(n-1, m, i-1)+m)%n;
	}

}
/*
结果:
第1次出列的人的编号为:2
第2次出列的人的编号为:5
第3次出列的人的编号为:8
第4次出列的人的编号为:1
第5次出列的人的编号为:6
第6次出列的人的编号为:0
第7次出列的人的编号为:7
第8次出列的人的编号为:4
第9次出列的人的编号为:9
第10次出列的人的编号为:3 
*/

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值