A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 yangying514 于 2014-5-30 23:36 编辑

主函数能看懂,约瑟夫环子函数看不懂啊,原题是出卖耶稣叛徒问题,15个人,3出,求最后一个
#include "stdio.h"
int main()
{
     int Josephus(int a,int b);  //函数声明
     int a[15];                   //定义一个数组,标志15个人
     int i;
     for(i=0;i<15;i++)            //循环实现1-15标志每个人
         a=i;
     printf("%d",Josephus(15,3));   //输出约瑟夫环算法的结果
     return 0;
}
int Josephus(int a,int b)      //约瑟夫环算法
{
         int    i,num=0;
         for    (i=2;i<=a;i++)   
         num=(num+b)%i;
         return    num+1;
}

评分

参与人数 1技术分 +1 收起 理由
傘が咲く + 1

查看全部评分

5 个回复

倒序浏览
等了一天了,没大神吗
回复 使用道具 举报
不懂呀,等大神
回复 使用道具 举报
递推公式:
f[i]代表着有I个人 做游戏的时候  最后出局人
   f[1]=0; f[i]=(f[i-1]+m)%i; (i>1)
公式推导:
太麻烦了 我直接给你贴个别人的帖子吧
这个比较通俗易懂
给出一个序列,从0~n-1编号。其中,k代表出列的序号的下一个,即k-1出列。

a 0, 1, …, k-1, k, k+1, …, n-1

那么,出列的序号是(m-1)%n,k=m%n(这个可真的是显而易见)。出列k-1后,序列变为

b 0, 1, …, k-2, k, k+1, …, n-1

然后,我们继续从n-1后延长这个序列,可以得到

c` 0, 1, …, k-2, k, k+1, …, n-1, n, n+1, …, n+k-2

我们取从k开始直到n+k-2这段序列。其实这段序列可以看作将序列b的0~k-2段移到了b序列的后面。这样,得到一个新的序列

c k, k+1, …, n-1, n, n+1, …, n+k-2

好了,整个序列c都减除一个k,得到

d 0, 1, …, n-2

c序列中的n-1, n, n+1都减除个k是什么?这个不需要关心,反正c序列是连续的,我们知道了头和尾,就能知道d序列是什么样的。

这样你看,从序列a到序列d,就是一个n序列到n-1序列的变化,约瑟夫环可以通过递推来获得最终结果。ok,继续向下。

剩下的就是根据n-1序列递推到n序列。假设在n-1序列中,也就是序列d中,我们知道了最终剩下的一个序号是x,那么如果知道了x转换到序列a中的编号x`,不就是知道了最终的结果了么?

下面我们就开始推导出序列a中x的序号是什么。

d->c,这个变换很容易,就是x+k;

c->b,这个变换是网上大家都一带而过的,也是令我郁闷的一个关键点。从b->c,其实就是0~k-2这段序列转换为n~n+k-2这段序列,那么再翻转回去,简单的就是%n,即(x+k)%n。%n以后,k~n-1这段序列值不会发生变化,而n~n+k-2这段序列则变成了0~k-2;这两段序列合起来,就是序列b。

于是乎,我们就知道了,x`=(x+k)%n。并且,k=m%n,所以x`=(x+m%n)%n=(x+m)%n。公式1就出来了:f[i]=(f[i-1]+m)%i。

好了,这个最后需要注意的就是从一开始,我们将n序列从0~n-1编号,所以依据公式1得出的序号是基于0开始的。

评分

参与人数 1技术分 +1 收起 理由
傘が咲く + 1

查看全部评分

回复 使用道具 举报
夏沫的黄昏′ 发表于 2014-5-29 11:19
递推公式:
f代表着有I个人 做游戏的时候  最后出局人
   f[1]=0; f=(f+m)%i; (i>1)

我慢慢看,谢谢
回复 使用道具 举报

这个跟c语言无关,是数学问题了-。-
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马