代码改变世界

Joseph Problem及其变形

2013-04-08 20:10  liuzq2013  阅读(234)  评论(0)    收藏  举报

一道数据结构的习题,貌似建议用循环链表来求解,只是我最近比较懒,所以直接采用用起来比较舒服的循环语句来求解了。

Joseph Problem

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 (n = 2*k). 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 < 8.

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

我的解答:

 

#include <iostream>
using namespace std;
int Ok(int k)
{
    int *p=new int[2*k+1];//判别生死状态的数组
    int count=0;//计数器
    int remainNum=2*k;//剩余人数
    int tryNum=k+1;//探测数
    bool judge=true;//设置这个值是为了比较方便地进行到下一个循环
    while(remainNum>k)
    {
        for(int i=1;i<=2*k;i++)
        {
            if(p[i]==0)
            {
                count++;
                if(count==tryNum) {if(i<=k){judge=false;} count=0;p[i]=1;remainNum--;}//如果数到tryNum,先判断是否是好人;剩余人数减一,重新数数
            }
        }
        if(judge==false)//探测数加一,其余参数重置
        {
            judge=true;
            remainNum=2*k;
            count=0;
            for(int i=1;i<=2*k;i++){p[i]=0;}
            tryNum++;
        }
    }
    delete p;
    return tryNum;
}
int main()
{
    int k,count=0;
    int a[10];//因为k是0到8,所以用这么一个小数组来保存结果
    while(k!=0)
    {
        cin>>k;
        if(k!=0)
        {
            a[count]=Ok(k);
            count++;
        }
    }
    for(int i=0;i<count;i++)
        cout<<a[i]<<endl;
}

 

一直输入,直到输入0结束,输出所有结果。

另外,附上简单的Joseph问题的程序:

#include <iostream>
using namespace std;
int remain(int n,int m)
{
    int *p=new int[n+1];//判断哪些人还活着
    int count=0;//计数器
    int remainNum=n;//剩余人数
    while(remainNum>1)//只看最后剩下的那个人的号码
    {
        for(int i=1;i<=n;i++)
        {
            if(p[i]==0)
            {
                count++;
                if(count==m) {count=0;p[i]=1;remainNum--;}//数到m就被杀掉,剩余人数减一,重新开始数数
            }
        }
    }
    for(int i=1;i<=n;i++)
    {
        if(p[i]==0) return i;//返回活到最后的人的号码
    }
    return 0;
}
int main()
{
    int n,m;
    cin>>n>>m;
    cout<<remain(n,m)<<endl;
}