poj1012

Posted 神犇(shenben)

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了poj1012相关的知识,希望对你有一定的参考价值。

Joseph
Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 52097   Accepted: 19838

Description

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. 

Input

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.

Output

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

Sample Input

3
4
0

Sample Output

5
30

Source

大致题意:

有k个坏人k个好人坐成一圈,前k个为好人(编号1~k),后k个为坏人(编号k+1~2k)

现在有一个报数m,从编号为1的人开始报数,报到m的人就要自动死去。

问当m为什么值时,可以使得在出现好人死亡之前,k个坏人先全部死掉?

 

PS:当前一轮第m个人死去后,下一轮的编号为1的人 为 前一轮编号为m+1的人

   前一轮恰好是最后一个人死掉,则下一轮循环回到开头那个人报“1”

 

解题思路:

经典的约瑟夫水题

 

由于k值比较少(1~13),暴力枚举m就可以了

递推公式为:

ans[i];  //第i轮杀掉 对应当前轮的编号为ans[i]的人

ans[0]=0;

ans[i]=(ans[i-1]+m-1)%(n-i+1);   (i>1  ,  总人数n=2k 则n-i为第i轮剩余的人数)

 

正规代码

#include<iostream>
#include<cstdio>
using namespace std;
int a[30],ans[30];//第i轮杀掉 对应当前轮的编号为ans[i]的人
int main(){
    int n,k,m;
    while(scanf("%d",&k)==1&&k){
        if(a[k]) {printf("%d\n",a[k]);continue;}//方便重复询问(数据范围太小) 
        m=1;//所求的最少的报数
        n=2*k;//总人数
        for(int i=1;i<=k;i++){
            ans[i]=(ans[i-1]+m-1)%(n-i+1);//n-i为剩余的人数,+1从下一个人开始 
            if(ans[i]<k){//ans[i]=>[0..k) 把好人杀掉了,m值不是所求
                i=0;
                m++;//枚举m值
            }
        }
        a[k]=m;
        printf("%d\n",m);
    }    
    return 0;
}

打表写法

#include<cstdio>
int k,a[17]={0,2,7,5,30,169,441,1872,7632,1740,93313,459901,1358657,2504881,1245064};
int main(){
    while(scanf("%d",&k)==1&&k)
        printf("%d\n",a[k]);
    return 0;
}

 

以上是关于poj1012的主要内容,如果未能解决你的问题,请参考以下文章

北大ACM(POJ1012-Joseph)

POJ 1012 Joseph

POJ 1012 Joseph

POJ 1012:Joseph

POJ1012 - Joseph

Java-POJ1012-Joseph