现在的位置: 首页 > 综合 > 正文

约瑟夫问题求解

2018年05月13日 ⁄ 综合 ⁄ 共 2544字 ⁄ 字号 评论关闭

问题描述:

据说著名犹太历史学家 Josephus有过以下的故事:在罗马人占领乔塔帕特后,39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止。然而Josephus 和他的朋友并不想遵从,Josephus要他的朋友先假装遵从,他将朋友与自己安排在第16个与第31个位置,于是逃过了这场死亡游戏。
17世纪的法国数学家加斯帕在《数目的游戏问题》中讲了这样一个故事:15个教徒和15 个非教徒在深海上遇险,必须将一半的人投入海中,其余的人才能幸免于难,于是想了一个办法:30个人围成一圆圈,从第一个人开始依次报数,每数到第九个人就将他扔入大海,如此循环进行直到仅余15个人为止。问怎样排法,才能使每次投入大海的都是非教徒。
*问题分析与算法设计
约瑟夫问题并不难,但求解的方法很多;题目的变化形式也很多。这里给出一种实现方法。
题目中30个人围成一圈,因而启发我们用一个循环的链来表示。可以使用结构数组来构成一个循环链。结构中有两个成员,其一为指向下一个人的指针,以构成环形的链;其二为该人是否被扔下海的标记,为1表示还在船上。从第一个人开始对还未扔下海的人进行计数,每数到9时,将结构中的标记改为0,表示该人已被扔下海了。这样循环计数直到有15个人被扔下海为止。

//author openxmpp@163.com

#include <iostream>
using namespace std;
#include <unistd.h>

template<typename T>
class Node
{
    template<typename U> friend Node<U>*  makeList( U start , U end );
    template<typename U> friend Node<U>*  removeNodeBySteps ( Node<U> * list, int steps );
    template<typename U> friend bool testJosephusLoop ( Node<U> * list );
public:
    Node<T> (T &value);
    Node<T> *getNext();
    T & getValue ();
private:
    Node *mNextNode ;
    T mValue;
};

template<typename T>
Node<T>::Node(T &value)
{
    mValue = value;
}

template<typename T>
Node<T> *
Node<T>::getNext()
{
    return mNextNode;
}

template<typename T>
T &
Node<T>::getValue()
{
    return mValue;
}

template<typename T>
Node<T> *
makeList(T start, T end)
{
    Node<T> * firstNode = 0;
    Node<T> * lastNode = 0;
    Node<T> * currentNode = 0;
    for ( T loop = start ; loop < end ; loop ++ )
    {
        if ( loop == start )
        {
            firstNode = new Node<T>(loop);
            currentNode = firstNode;
            continue;
        }
        else if ( loop < end )
        {
            Node<T> *tmpNode = new Node<T>(loop);
            currentNode -> mNextNode = tmpNode;
            currentNode = tmpNode;
        }
    }
    lastNode = new Node<T>(end);
    currentNode -> mNextNode = lastNode;
    lastNode -> mNextNode = firstNode;
    return lastNode;
}

template<typename U>
Node<U>*
removeNodeBySteps ( Node<U> * list, int steps )
{
    int cnt = 0;
    while ( true )
    {
        if ( list -> mNextNode == list )
        {
            cout << " the WINNER is  " << list->mValue << endl ;
            return list;
        }
        else
        {
            if ( cnt == steps - 1 )
            {
                Node<U> *nextNode = list->mNextNode;
                cout << " the player is out " << nextNode->mValue << endl;
                list->mNextNode = nextNode->mNextNode;
                delete nextNode ;
                nextNode = 0;
                cnt = 0 ;
            }
            else
            {
                cnt ++ ;
                    list = list->mNextNode ;
            }
        }
    }
}

template<typename U>
bool
testJosephusLoop( Node<U> * list )
{
    if ( 0 == list )
    {
        return false;
    }
    Node<U> * firstNode = list ;
    while ( true )
    {
        if ( list->mNextNode == firstNode )
        {
            return true;
        }
        else if ( list && list->mNextNode )
        {
            list = list -> mNextNode;
        }
        else if ( list || list->mNextNode )
        {
            return false;
        }
    }
    return false;
}

void uniTest()
{
    Node<int> * result = makeList(1,9);
    bool check = testJosephusLoop(result);
    cout << "check result "<< check	<<endl;
    removeNodeBySteps<int>(result,5);

    Node<long> * result2 = makeList<long>(10,20);
    bool check2 = testJosephusLoop(result2);
    removeNodeBySteps(result2,3);
}

int main(int argc, char const *argv[])
{
    uniTest();
    return 0;
}

抱歉!评论已关闭.