ACM PKU 2244 Eeny Meeny Moo 约瑟夫问题

http://acm.pku.edu.cn/JudgeOnline/problem?id=2244 
     在没有明白约瑟夫问题之前,只能用模拟来做.
      约瑟夫问题是这样的:
      假设n个人,编号为1到n,排成一个圈,顺时针从1开始数字m,数到m的人杀了,剩下的人继续游戏.活到最后的一个人是胜利者.一般来说需要编程求解最后一个人的编号.
      思路是这样的:
     假设当前剩下i个人(i<=n),显然这一轮m要挂(因为总是从1开始数).经过这一轮,剩下的人是:1 2 3 ... m- 1 m + 1 ... i, 我们将从m+1开始的数映射成1, 则m+2对应2, n对应i - m, 1对应成i - m + 1  m - 1对应i - 1,那么现在的问题变成了已知i - 1个人进行循环报数m,求出去的人的序号。假设已经求出了i- 1个人循环报数下最后一个出去的人的序号X0,那么它在n个人中的序号X1=(X0+ m - 1) % n + 1,  最初的X0=1 ,反复迭代X0和X1可以求出.
     简单约瑟夫问题的解法:
#include <stdio.h >
main()
{
    
int n, m,i, s=0;
    printf( 
"N  M  =  "); scanf("%d%d ",&n,&m);
    
for(i=2;i<=n;i++)s=(s+m)%i;
    printf(
"The winner is %d\n ", s+1);
}
  

      这倒题其实不是完全的约瑟夫问题,而是稍微变了形.呵呵,聪明的读者自己发现!这一点费了我很久的时间,还害我逃了课被点名...
    这道题的我解法是这样的.

#include   <stdio.h >
int y(int n,int m)
{
    
int s=1,i;
    
for(i=2;i<=n-1;i++)
        s
=(s+m-1)%i+1;
    
return s+1;

}


main()
{
    
int m,n;
    
    
while(1)
    
{
    scanf(
"%d",&n);
    
if(n==0)break;
     
for(m=1;;)
     
{
         
if(y(n,m)==2)break;
         m
++;
     }

   

    printf(
"%d\n",m);
    
    }

}


       读一个数处理一个数, Memory 68K,时间31MS,如果觉得效率不高. 优化的办法是打表~

    

posted on 2007-11-06 15:46 流牛ζ木马 阅读(3003) 评论(6)  编辑 收藏 引用

评论

# re: ACM PKU 2244 Eeny Meeny Moo 约瑟夫问题 2007-11-10 02:09 Run&Run

细节的东西好难把握哦,
1. s==0;for(i=2;i<=n;i++)s=(s+m)%i;
2. s==1;for(i=2;i<=n-1;i++)s=(s+m-1)%i+1;
为什么这两个地方不一样,不太看的明白,能解释一下吗?
  回复  更多评论   

# re: ACM PKU 2244 Eeny Meeny Moo 约瑟夫问题 2007-11-10 10:15 流牛ζ木马

@Run&amp;Run

呵呵,其实很简单,你纸上画一下就知道了
s==0;for(i=2;i<=n;i++)s=(s+m)%i;
是指n个人,编号从0到n-1 .输出的时候必须输出s+1 (编号s的人是第s+1个人)

而s==1;for(i=2;i<=n-1;i++)s=(s+m-1)%i+1; ㈠是有n-1个人,编号是从1开始的(题目其实是除去了第一个人的约瑟夫问题,所以只有n-1个人);㈡从约瑟夫问题回归到在这道题中,发现编号并不是真正从1开始的,第一个人首先出去.所以依次向后移动一个编号,故也需要输出s+1 ,和上面的s+1不同,这一点注意.
我这样写是为了方便自己理解,当然从数学的角度,你完全可以化简它

其实我自己做的时候并没有注意到这些细节,也没有把两个s+1拿出去比较,这些东西也不是需要强记硬背的,重点还是要看透彻问题的本身

以上是一点心得,呵呵,谢谢关注,希望我的解答对你有帮助.  回复  更多评论   

# re: ACM PKU 2244 Eeny Meeny Moo 约瑟夫问题 2007-11-10 13:12 Run&Run

终于搞懂了.唉,想了我整整一个晚上加一个上午.我想这题这样写更好些.
2. m=0;for(i=2;i<=n-1;i++)s=(s+m)%i;
if(s==0)break;
这样写和<1>在细节问题上的处理就一样了.
我这样交的,AC了.
PS:你真太牛了,太佩服你了.  回复  更多评论   

# re: ACM PKU 2244 Eeny Meeny Moo 约瑟夫问题 2009-02-07 23:14 tzzhwj

刚才打个表A了,还是我数学不够好啊。谢谢啊  回复  更多评论   

# re: ACM PKU 2244 Eeny Meeny Moo 约瑟夫问题 2009-07-05 11:53 solofancy

子函数跟约瑟夫一样的嘛。。。。主函数写成y(n-1,m)==1就好了吧,16ms  回复  更多评论   

# re: ACM PKU 2244 Eeny Meeny Moo 约瑟夫问题 2010-06-17 21:51 vampire

楼主的程序运行的结果不对啊?  回复  更多评论   


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


<2007年11月>
28293031123
45678910
11121314151617
18192021222324
2526272829301
2345678

导航

统计

公告

MY Email/MSN :mars1021@163.com QQ : 27402040 流牛ζ木马

常用链接

留言簿(6)

随笔档案

相册

搜索

最新随笔

最新评论

阅读排行榜

评论排行榜