约瑟夫环问题
2015-08-31 14:41
363 查看
约瑟夫环(约瑟夫问题)是一个数学的应用问题:已知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
*/
先给出一个通式: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
*/
相关文章推荐
- java对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- Android IPC进程间通讯机制
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- 介绍一款信息管理系统的开源框架---jeecg
- 聚类算法之kmeans算法java版本
- java实现 PageRank算法
- PropertyChangeListener简单理解
- 插入排序
- 冒泡排序
- 堆排序
- 快速排序
- 二叉查找树
- [原创]java局域网聊天系统