| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 2386 人关注过本帖
标题:有没有谁写过 传教士 与野人过河 的问题,问个问题
只看楼主 加入收藏
tfxanxing
Rank: 3Rank: 3
等 级:论坛游侠
威 望:2
帖 子:82
专家分:165
注 册:2010-5-7
结帖率:80%
收藏
已结贴  问题点数:40 回复次数:7 
有没有谁写过 传教士 与野人过河 的问题,问个问题
(既然做过我就写下大概意思)问题大概意思:
有一条河,同一岸边有M个野人和M个传教士,有一条船,最多能载N个人,
任何情况下野人数不能大于传教士的数(传教士数为0除外),
求怎么过河?

我写的运行后只能解决相邻的数的问题,比如 M=3,N=2, 4,3 ; 5,4;7,6;等等但是一有间隔就不行,比如 7,5就不行

有经验的分享分享啊!!
搜索更多相关主题的帖子: 野人 传教士 过河 
2010-12-09 22:02
御坂美琴
Rank: 11Rank: 11Rank: 11Rank: 11
来 自:魔術の禁書目錄
等 级:小飞侠
威 望:9
帖 子:952
专家分:2929
注 册:2010-8-18
收藏
得分:40 
最简单的做法是直接bfs,反正状态数很少,只有m*m种

[ 本帖最后由 御坂美琴 于 2010-12-9 22:06 编辑 ]

永远为正义而奋斗,锄强扶弱的Level 5 超能力者
とある魔術の禁書目錄インデックス__御み坂さか美み琴こと
http://bbs.bccn.net/space.php?action=threads&uid=483997
2010-12-09 22:05
御坂美琴
Rank: 11Rank: 11Rank: 11Rank: 11
来 自:魔術の禁書目錄
等 级:小飞侠
威 望:9
帖 子:952
专家分:2929
注 册:2010-8-18
收藏
得分:0 
不过,当N>=4的时候,不管M是多大,都是成立的,你能发一下你的程序不?

永远为正义而奋斗,锄强扶弱的Level 5 超能力者
とある魔術の禁書目錄インデックス__御み坂さか美み琴こと
http://bbs.bccn.net/space.php?action=threads&uid=483997
2010-12-09 22:09
tfxanxing
Rank: 3Rank: 3
等 级:论坛游侠
威 望:2
帖 子:82
专家分:165
注 册:2010-5-7
收藏
得分:0 
回复 3楼 御坂美琴
好的,不过我的程序好像有点大啊
要是有时间就看看,多谢了

我把大概思想在程序中注释了


#include<stdio.h>
#include<iostream>

typedef struct man{            //野人和传教士的分布有三状况,河左边、河右边、船上。定义一个结构体,用于存放 河左边、河右边、船上 的野人和传教士的数目
    int left_wild;
    int left_church;
    int boat_wild;
    int boat_church;
    int right_wild;
    int right_church;
    bool useful;    //没用的,不用管
    struct man *next;
    struct man *back;
    man()
    {
        left_wild=0;
        left_church=0;
        boat_wild=0;
        boat_church=0;
        right_wild=0;
        right_church=0;
        useful=false;
        next=NULL;
        back=NULL;
    }
    man(int lw,int lc,int bw,int bc,int rw,int rc,bool use,struct man *n=NULL,struct man *ba=NULL)
    {
        left_wild=lw;
        left_church=lc;
        boat_wild=bw;
        boat_church=bc;
        right_wild=rw;
        right_church=rc;
        useful=use;
        next=n;
        back=ba;
    }

}Manstate;

bool is_next(Manstate *obj)                //这是确定找出的一个状态是不是满足要求(野人>传教士)
{
    if(obj->boat_church>0 || obj->boat_wild>0)
    {
        if(obj->left_church>=0 && obj->left_wild>=0 && obj->right_church>=0 && obj->right_wild>=0)
            if(obj->left_church >= obj->left_wild || obj->left_church==0)
                if(obj->right_church >= obj->right_wild || obj->right_church==0)
                    if(obj->boat_church >= obj->boat_wild || obj->boat_church==0)
                        if((obj->left_wild+obj->boat_wild <= obj->left_church+obj->boat_church || (obj->left_church+obj->boat_church==0)) && (obj->right_wild+obj->boat_wild <= obj->right_church+obj->boat_church || obj->right_church+obj->boat_church==0))
                            return true;
    }
    else if(obj->boat_church==0 && obj->boat_wild==0 && obj->left_church==0 && obj->left_wild==0)
        return true;

    return false;
}

bool copynode(Manstate *obj,Manstate *source)    //这儿是复制结构体里面的数据
{
    obj->boat_church=source->boat_church;
    obj->boat_wild=source->boat_wild;
    obj->left_church=source->left_church;
    obj->left_wild=source->left_wild;
    obj->right_church=source->right_church;
    obj->right_wild=source->right_wild;
    obj->useful=source->useful;
    obj->next=source->next;
    obj->back=source->back;
    return true;
}

bool check(Manstate *obj,Manstate *source)    //这是判断两个结构体里的数据(不算指针)是不是相同
{
    if(obj->boat_church!=source->boat_church)
        return false;
    if(obj->boat_wild!=source->boat_wild)
        return false;
    if(obj->left_church!=source->left_church)
        return false;
    if(obj->left_wild!=source->left_wild)
        return false;
    if(obj->right_church!=source->right_church)
        return false;
    if(obj->right_wild!=source->right_wild)
        return false;
    return true;
}

void acrossriver(Manstate *obj,int num)         //传入一个刚开始的野人和传教士分布的结构体,再进行扩展,寻找下一种情况,直到全过河为止
{
    int i=0,j=0;
    bool flag=false;
    Manstate *now,*tail,*previous;
    tail=obj;
    previous=obj;

    while(tail->left_church>0 || tail->left_wild>0)        //这儿是寻找从  左岸  上船的各种情况
    {
        now=new Manstate();
        for(i=num;i>=0;i--)
        {
            for(j=num-i;j>=0;j--)
            {
                copynode(now,tail);
                now->left_wild-=i;
                now->left_church-=j;
                now->boat_church+=j;
                now->boat_wild+=i;
                if(is_next(now))
                {
                    if(tail->back && !check(now,tail->back))   //判断符合条件并且和前一种运输状况不同
                    {
                        tail->next=now;
                        now->back=tail;
                        tail=tail->next;
                        flag=true;
                        break;
                    }
                    else if(!tail->back)         //如果刚开始就直接连在链表末尾,(下同)
                    {
                        tail->next=now;
                        now->back=tail;
                        tail=tail->next;
                        flag=true;
                        break;
                    }
                }
            }
            if(flag)
            {
                flag=false;
                break;
            }
        }
        if(tail->left_church==0 && tail->left_wild==0)                //如果左岸全没人了,跳出这层循环
        {
            now=new Manstate();
            copynode(now,tail);
            now->right_church+=now->boat_church;
            now->right_wild+=now->boat_wild;
            now->boat_church=0;
            now->boat_wild=0;
            tail->next=now;
            now->back=tail;
            tail=tail->next;
            break;
        }
        now=new Manstate();
        copynode(now,tail);
        now->right_church+=now->boat_church;    //把船上的人都放到右岸,形成一个节点
        now->right_wild+=now->boat_wild;
        now->boat_church=0;
        now->boat_wild=0;
        tail->next=now;
        now->back=tail;
        tail=tail->next;
        
        now=new Manstate();
        for(i=0;i<=num;i++)                    //寻找从右岸上船的各种情况
        {
            for(j=0;j<=num-i;j++)
            {
                copynode(now,tail);
                now->right_church-=i;
                now->right_wild-=j;
                now->boat_church+=i;
                now->boat_wild+=j;
                if(is_next(now))
                {
                    if(tail->back && !check(now,tail->back))    //判断符合条件并且和前一种状况不同
                    {
                        tail->next=now;
                        now->back=tail;
                        tail=tail->next;
                        flag=true;
                        break;
                    }
                    else if(!tail->back)
                    {
                        tail->next=now;
                        now->back=tail;
                        tail=tail->next;
                        flag=true;
                        break;
                    }
                }
            }
            if(flag)
            {
                flag=false;
                break;
            }
        }
        now=new Manstate();            //把船上的人都放到右岸,形成一个节点
        copynode(now,tail);
        now->left_church+=now->boat_church;
        now->left_wild+=now->boat_wild;
        now->boat_church=0;
        now->boat_wild=0;
        tail->next=now;
        now->back=tail;
        tail=tail->next;
    }                                                            //下面的是输出
    tail=obj;
    printf("%dc %dw ------ %dc %dw ------ %dc %dw\n",tail->left_church,tail->left_wild,tail->boat_church,tail->boat_wild,tail->right_church,tail->right_wild);
    tail=tail->next;

    flag=true;
    int count=0;
    while(tail)
    {
        count++;
        if(flag)
        {
            if(count%2==0)
                flag=!flag;
            printf("%dc %dw ----> %dc %dw ----> %dc %dw\n",tail->left_church,tail->left_wild,tail->boat_church,tail->boat_wild,tail->right_church,tail->right_wild);
        }
        else
        {
            if(count%2==0)
                flag=!flag;
            printf("%dc %dw <---- %dc %dw <---- %dc %dw\n",tail->left_church,tail->left_wild,tail->boat_church,tail->boat_wild,tail->right_church,tail->right_wild);
        }
        tail=tail->next;
    }

}

void main()
{
    Manstate initman;
   
    int num;
    printf("input the number of wildman or churchman:");
    scanf("%d",&initman.left_wild);
    initman.left_church=initman.left_wild;
    printf("input the number of once across by boat:");
    scanf("%d",&num);




    acrossriver(&initman,num);
   
//    printf("%d    %d     %d\n",initman.left_wild,initman.left_church,num);

    system("pause");
}
2010-12-09 22:48
御坂美琴
Rank: 11Rank: 11Rank: 11Rank: 11
来 自:魔術の禁書目錄
等 级:小飞侠
威 望:9
帖 子:952
专家分:2929
注 册:2010-8-18
收藏
得分:0 
晕,其实你没必要刻意考虑船上的,只记录河岸一边的情况就可以了

永远为正义而奋斗,锄强扶弱的Level 5 超能力者
とある魔術の禁書目錄インデックス__御み坂さか美み琴こと
http://bbs.bccn.net/space.php?action=threads&uid=483997
2010-12-09 22:52
tfxanxing
Rank: 3Rank: 3
等 级:论坛游侠
威 望:2
帖 子:82
专家分:165
注 册:2010-5-7
收藏
得分:0 
回复 5楼 御坂美琴
你说的就是只对两岸的野人和传教士操作对吧?但是遍历可能运输情况的时候还是要考虑 船上的 野人大于传教士  的啊,

我觉得问题的关键不在这儿吧!
2010-12-09 23:14
御坂美琴
Rank: 11Rank: 11Rank: 11Rank: 11
来 自:魔術の禁書目錄
等 级:小飞侠
威 望:9
帖 子:952
专家分:2929
注 册:2010-8-18
收藏
得分:0 
你其实记录一边,另一边就知道情况了,你要改一边的情况的时候,再判断船的情况,船的情况就是岸边变化的情况
你其实只需要一个int state[100][100]的数组,就足够记录下m=100的所有可能性了
比如 state[4][2] = 3表示河的这边,有四个野人两个传教士,这种状态到达过,并且是在第三步操作到达的
用这个数组就可以记录每个状态多少步到达了,然后再使用bfs解决就行
但我分析了一下,其实不需要bfs,模式太固定了,只有一种可能

永远为正义而奋斗,锄强扶弱的Level 5 超能力者
とある魔術の禁書目錄インデックス__御み坂さか美み琴こと
http://bbs.bccn.net/space.php?action=threads&uid=483997
2010-12-09 23:39
tfxanxing
Rank: 3Rank: 3
等 级:论坛游侠
威 望:2
帖 子:82
专家分:165
注 册:2010-5-7
收藏
得分:0 
回复 6楼 tfxanxing
好的 ,谢谢, 我再做做看
2010-12-10 13:04
快速回复:有没有谁写过 传教士 与野人过河 的问题,问个问题
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.029482 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved