发新话题
打印

[讨论]算法与数据结构类 有关修道士与野人渡河问题的求解

[讨论]算法与数据结构类 有关修道士与野人渡河问题的求解

议题提交:寒潮
信息来源:邪恶八进制信息安全团队(www.eviloctal.com

请教“修道士与野人问题”
有N个修道士和N个野人准备渡河,但只有一条能容纳C人的小船,为了防止野人侵犯修道士,要求无论在何处,修道士的个数不得少于野人的人数(除非修道士的个数为0)。两种人都会划船,设计一算法,确定他们能否过河,若能,找出一个小船来回次数最少的方案。。

自己想了半天也没想出来,这里不限制用什么语言来写
但最好是用C语言来编写.(因为我只会C )


--Administrators--
主题提出算法的讨论很好 但是应该注意讨论的意思就是自己已经做过细致的研究 在一定程度上解决了部分问题 否则只是个单纯的提问 不符合讨论的要求
就本主题 楼主想和别人进行交流 应该自己先写出一个代码 哪怕不完善 至少也向别人证明您做过努力 并非单纯提问...
注意看置顶主题 对讨论主题的描述...
对于VIP组成员不直接删除主题..但是2天内没有一帖人给出代码的 将删除
我对天大喊“我不帅” 天对我说“你撒谎”

TOP

这个我以前学人工智能的时侯有做过.
主要还是模拟我们思维的方式进行编写.
可以用一个二维数组置标志的方法进行.
在我纯真年少時,有一個女生,她願意爲我失去生命,她意志堅定地說:你再纏著我,我就去死! 在我負笈外地時,有一個女生,她願意等我到下輩子,她溫柔婉約地說:你想成爲我男友?等下輩子!! 在我窮困潦倒時,有一個女生,她願意與我共赴黃泉,她眨著紅眼說:你再不還錢,我和你同歸于盡!

TOP

我也学过,过程:运过去c个野人,再运回来一个,在运过去c-1个传教士,然后运回来1个野人一个传教士。这时两边都处于平衡状态,重复上一过程。
程序不好写。ps:自己水平不行啊。
to be a better man ~~~

TOP

到这个网址搜索"修道士"或者"传教士"

做作业必备!

http://search.csdn.net/
流氓会武术,谁都挡不住. http://hi.baidu.com/zvrop

TOP

谢谢楼上啦
找到如下代码:

struct INFO
{
    int nSavage;        //    岸边野人的数量 开始为3 全部到对岸为0
    int nBoanerges;        //    岸边传教士的数量 开始为3 全部到对岸为0
    int nSide;            //    船的位置 在此岸为-1 彼岸为1
    int nMoveSavage;    //    渡河的野人的数量,用于递归时记录操作状态
    int nMoveBoanerges;    //    渡河的传教士的数量,用于递归时记录操作状态
    INFO* pPrevious;
    INFO* pNext;
};

//    判断是否有下一个满足条件的渡河方案
bool GetNextMove(INFO* pInfo)
{
    //    渡船的优先顺序
    //    此岸数量多优先,野人优先,彼岸数量少优先,传教士优先。
    const int nStoreCount = 5;
    struct STORE
    {
        int nSavage;
        int nBoanerges;
    };

    STORE listStore[nStoreCount];
    if (pInfo->nSide == -1)
    {
        listStore[0].nSavage = 2;
        listStore[0].nBoanerges = 0;
        listStore[1].nSavage = 1;
        listStore[1].nBoanerges = 1;
        listStore[2].nSavage = 0;
        listStore[2].nBoanerges = 2;
        listStore[3].nSavage = 1;
        listStore[3].nBoanerges = 0;
        listStore[4].nSavage = 0;
        listStore[4].nBoanerges = 1;
    }
    else
    {
        listStore[0].nSavage = 0;
        listStore[0].nBoanerges = 1;
        listStore[1].nSavage = 1;
        listStore[1].nBoanerges = 0;
        listStore[2].nSavage = 0;
        listStore[2].nBoanerges = 2;
        listStore[3].nSavage = 1;
        listStore[3].nBoanerges = 1;
        listStore[4].nSavage = 2;
        listStore[4].nBoanerges = 0;
    }

    int iStart;
    if (pInfo->nMoveSavage == 0 && pInfo->nMoveBoanerges == 0)
    {
        iStart = 0;
    }
    else
    {
        for (iStart=0; iStart<nStoreCount; iStart++)
        {
            if (pInfo->nMoveSavage == listStore[iStart].nSavage && pInfo->nMoveBoanerges == listStore[iStart].nBoanerges)
                break;
        }
        iStart++;
    }
   
    if (iStart < nStoreCount)
    {
        int i;
        for (i=iStart; i<nStoreCount; i++)
        {
            int nSideSavage = pInfo->nSavage + listStore.nSavage * pInfo->nSide;
            int nSideBoanerges = pInfo->nBoanerges + listStore.nBoanerges * pInfo->nSide;
            int nBesideSavage = 3 - nSideSavage;
            int nBesideBoanerges = 3 - nSideBoanerges;

            //    传教士数量大于等于野人或为零
            if ((nSideSavage<=nSideBoanerges || nSideBoanerges == 0) &&
                (nBesideSavage<=nBesideBoanerges || nBesideBoanerges == 0) &&
                nSideSavage>=0 && nSideBoanerges>=0 && nBesideSavage>=0 && nBesideBoanerges>=0)
            {
                //    如果本此解等于上次,放弃
                if (pInfo->pPrevious != NULL)
                {
                    if (pInfo->pPrevious->nMoveBoanerges == listStore.nBoanerges &&
                        pInfo->pPrevious->nMoveSavage == listStore.nSavage)
                    continue;
                }
                break;
            }
        }
        if (i < nStoreCount)
        {
            pInfo->nMoveSavage = listStore.nSavage;
            pInfo->nMoveBoanerges = listStore.nBoanerges;
            return true;
        }
    }

    return false;
}

//    递归函数
bool Ship(INFO* pInfo)
{
    if (GetNextMove(pInfo))
    {
        INFO* pNew = new INFO;
        pNew->nSavage = pInfo->nSavage + pInfo->nMoveSavage * (pInfo->nSide);
        pNew->nBoanerges = pInfo->nBoanerges + pInfo->nMoveBoanerges * (pInfo->nSide);
        pNew->nSide = (pInfo->nSide) * (-1);
        pNew->pPrevious = pInfo;
        pNew->pNext = NULL;
        pNew->nMoveSavage = 0;
        pNew->nMoveBoanerges = 0;
        pInfo->pNext = pNew;
        if (pNew->nSavage == 0 && pNew->nBoanerges == 0) return true;    //    完成
        return Ship(pNew);
    }
    else
    {
        INFO* pPre = pInfo->pPrevious;
        if (pPre == NULL) return false;        //    无解
        delete pInfo;
        pPre->pNext = NULL;
        return Ship(pPre);
    }
    return true;
}

int main(int argc, char* argv[])
{
    INFO* pHead = new INFO;
    pHead->nSavage = 3;
    pHead->nBoanerges = 3;
    pHead->nSide = -1;
    pHead->pPrevious = NULL;
    pHead->pNext = NULL;
    pHead->nMoveSavage = 0;
    pHead->nMoveBoanerges = 0;

    if (Ship(pHead))
    {
        printf("渡河过程如下:\n");
        INFO* pInfo = pHead;
        while (pInfo->pNext)
        {
            printf("渡河方向:%s  人数:野人%d - 传教士%d  此岸野人数:%d, 传教士数:%d\n",
                (pInfo->nSide == -1) ? "-->" : "<--", pInfo->nMoveSavage,
                pInfo->nMoveBoanerges, pInfo->nSavage, pInfo->nBoanerges);
            pInfo = pInfo->pNext;
        }
        printf("渡河完成。");
    }
    else
    {
        printf("此题无解!");
    }

    //    删除链表
    while (pHead)
    {
        INFO* pTemp = pHead->pNext;
        delete pHead;
        pHead=pTemp;
    }
    pHead = NULL;

    printf("请结束程序。");
    return 0;
}

程序结果


渡河过程如下:
渡河方向:-->  人数:野人2 - 传教士0  此岸野人数:3, 传教士数:3
渡河方向:<--  人数:野人1 - 传教士0  此岸野人数:1, 传教士数:3
渡河方向:-->  人数:野人2 - 传教士0  此岸野人数:2, 传教士数:3
渡河方向:<--  人数:野人1 - 传教士0  此岸野人数:0, 传教士数:3
渡河方向:-->  人数:野人0 - 传教士2  此岸野人数:1, 传教士数:3
渡河方向:<--  人数:野人1 - 传教士1  此岸野人数:1, 传教士数:1
渡河方向:-->  人数:野人0 - 传教士2  此岸野人数:2, 传教士数:2
渡河方向:<--  人数:野人1 - 传教士0  此岸野人数:2, 传教士数:0
渡河方向:-->  人数:野人2 - 传教士0  此岸野人数:3, 传教士数:0
渡河方向:<--  人数:野人0 - 传教士1  此岸野人数:1, 传教士数:0
渡河方向:-->  人数:野人1 - 传教士1  此岸野人数:1, 传教士数:1
渡河完成。请结束程序。Press any key to continue
我对天大喊“我不帅” 天对我说“你撒谎”

TOP

代码比较长,看了一半实在看不下去啦...
找了好久没找到用C语言完成的,看来用C语言实现起来比较困难
我对天大喊“我不帅” 天对我说“你撒谎”

TOP

晕倒.
这个程序没用到C++什么新特性.
C里面稍微改动很小的细节就可以过
用了个双向链表而已
完全是C的内容.
连入侵者都敢说自己在做网络安全。关键大家是真正为安全作过什么?

TOP

寒潮就是要C的代码...
请加47809945   100%通过!每个月总有那么几天,您的网络会受到黑客的攻击--坐立不安,烦躁无力,使用虎虎开发的"月月舒"防火墙,超轻超薄,易于携带,提供由内到外的全方位保护,即使流量再大,也可以冲浪自如,再也不用担心侧漏啦。

TOP

这个代码就是直接放到C编译器就可以用啊
即便是有error或者warning
也是很小的细节.稍微改一下就可以了
整体来说这本身就是一个C程序
并没用到OO.
连入侵者都敢说自己在做网络安全。关键大家是真正为安全作过什么?

TOP

发新话题