传教士和野人问题

zzw820626 2003-12-14 03:22:45
请问传教士和野人问题怎么用c++实现?
...全文
386 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
computer386 2003-12-14
  • 打赏
  • 举报
回复
数学建模老师讲过,挺有意思的,先求出所有可行状态.再把两边的可行状态连起来.
ppstay 2003-12-14
  • 打赏
  • 举报
回复
八.【程序清单】
1.state.h

class state
{
protected:
int iStateNumber;//状态编号
int iopNumber;//当前最大操作编号
public:
int iCenobite;//修道士数
int iWildManA;//会划船的野人数
int iWildManB;//不会划船的野人数
int iBank;//0表示此岸,1表示彼岸
state * pFather,* pChild;//指向父、子结点的指针
state(int,int,int,int);
~state();
int setNumber(int);
int getNumber();
void operate();
int isError();
int getOpNumber();
void setOpNumber(int);
int addOpNumber();
void getState(int *);
int isTarget();
int isStart();

static int opp[7][3];
static int Max[3];
};

2.state.cpp

#include "state.h"
#include <iostream.h>
#include <process.h>
//用四元组构造一个state结点
state::state(int cenobite,int wildManA,int wildManB,int bank)
{
iStateNumber=0;
iopNumber=0;
iCenobite=cenobite;
iWildManA=wildManA;
iWildManB=wildManB;
iBank=bank;
pFather=0;
pChild=0;
}
//设置状态编号
int state::setNumber(int stateNumber)
{
this->iStateNumber=stateNumber;
return stateNumber;
}
//获得状态编号
int state::getNumber()
{
return iStateNumber;
}
//获得当前操作编号
int state::getOpNumber()
{
return iopNumber;
}
//设置当前操作编号
void state::setOpNumber(int opNumber)
{
this->iopNumber=opNumber;
}
//当前操作编号加1
int state::addOpNumber()
{
if(iopNumber>6)
return iopNumber;
else{
iopNumber++;
return iopNumber;
}
}
//获取当前四元组状态,放在state里面
void state::getState(int * state)
{
state[0]=iCenobite;
state[1]=iWildManA;
state[2]=iWildManB;
state[3]=iBank;
}
//根据当前设置的操作编号进行操作
void state::operate()
{
if(iBank==0){
iCenobite=iCenobite-state::opp[iopNumber][0];
iWildManA=iWildManA-state::opp[iopNumber][1];
iWildManB=iWildManB-state::opp[iopNumber][2];
iBank=1;
}
else{
iCenobite=iCenobite+state::opp[iopNumber][0];
iWildManA=iWildManA+state::opp[iopNumber][1];
iWildManB=iWildManB+state::opp[iopNumber][2];
iBank=0;
}
}
//判断当前结点是否是非法结点
int state::isError()
{
if(iCenobite && iCenobite<iWildManA+iWildManB)
return 1;
if(3-iCenobite && 3-iCenobite<3-iWildManA-iWildManB)
return 1;
if(iCenobite<0||iWildManA<0||iWildManB<0)
return 1;
if(iCenobite>3||iWildManA>2||iWildManB>1)
return 1;
return 0;
}
//判断当前结点是否是目标结点
int state::isTarget()
{
if(!iCenobite && !iWildManA && !iWildManB && iBank)
return 1;
else
return 0;
}
//判断当前结点是否为初始结点
int state::isStart()
{
if(iCenobite==3&&iWildManA==2&&iWildManB==1&&iBank==0)
return 1;
return 0;
}

3.river.h

#include "state.h"

class river
{
int count;
public:
state * phead;//指向链表的第一个(最新生成的)结点
river();
void extend();
int isTwice();
void remount();
static int iSuccess;
};

4.river.cpp

#include "river.h"
#include <iostream.h>

//构造函数
river::river()
{
count=0;
phead=new state(3,2,1,0);//生成初始结点
}
//扩展当前结点
void river::extend()
{
int temp[4];
phead->getState(temp);
phead->pChild=new state(temp[0],temp[1],temp[2],temp[3]);
phead->pChild->pFather=phead;
phead=phead->pChild;
phead->setOpNumber(phead->pFather->getOpNumber());
phead->setNumber(this->phead->pFather->getNumber()+1);
phead->operate();
phead->setOpNumber(0);
}
//判断头指针所指结点是否已经生成
int river::isTwice()
{
state * current=phead->pFather;
while(current){
if(current->iCenobite==phead->iCenobite &&
current->iWildManA==phead->iWildManA &&
current->iWildManB==phead->iWildManB &&
current->iBank==phead->iBank )
return 1;
current=current->pFather;
}
return 0;
}
//回溯到上一结点
void river::remount()
{
phead=phead->pFather;
phead->addOpNumber();
}
//在main函数之前初始化静态成员变量
int state::opp[7][3]={{2,0,0},{1,0,0},{1,1,0},{0,1,0},
{0,2,0},{0,1,1},{1,0,1}};
int state::Max[3]={3,2,1};
int river::iSuccess=0;
int state::total=0;
void main(void)
{
river River;
for(;;)
{
River.extend();//扩展结点
//判断是否保留此结点
if(River.phead->isError() || River.isTwice())
River.remount();//回溯
//判断是否需要继续回溯
while(River.phead->getOpNumber()>6 && !River.phead->isStart())
River.remount();
if(River.phead->isTarget()){//搜索到一种方法
river::iSuccess++;
cout<<"\nFind one method! the number is "
<<river::iSuccess <<"\n";
state * temp;
temp=River.phead;
while(temp->pFather){
temp=temp->pFather;
}
while(temp){
cout<<"("<<temp->iCenobite<<","<<
temp->iWildManA<<","<<
temp->iWildManB<<","<<
temp->iBank<<")->";
temp=temp->pChild;
}
River.remount();//回溯以继续搜索其他方法
}
//搜索完所有结点
if(River.phead->isStart() && River.phead->getOpNumber()==7){
cout<<"\nComplete!\n";
cout<<"\n"<<river::iSuccess
<<" methods have been found!\n";
break;
}
}
}
ppstay 2003-12-14
  • 打赏
  • 举报
回复
七.【运行结果】
Find one method! the number is 1
(3,2,1,0)->(2,1,1,1)->(3,1,1,0)->(3,0,0,1)->(3,1,0,0)->(1,1,0,1)->(2,1,1,0)->(0,1,1,1)->(0,2,1,0)->(0,0,1,1)->(1,0,1,0)->(0,0,0,1)
Find one method! the number is 2
(3,2,1,0)->(2,1,1,1)->(3,1,1,0)->(3,0,0,1)->(3,1,0,0)->(1,1,0,1)->(2,1,1,0)->(0,1,1,1)->(0,2,1,0)->(0,0,1,1)->(0,1,1,0)->(0,0,0,1)
Find one method! the number is 3
(3,2,1,0)->(2,1,1,1)->(3,1,1,0)->(3,0,0,1)->(3,1,0,0)->(1,1,0,1)->(2,1,1,0)->(0,1,1,1)->(0,2,1,0)->(0,1,0,1)->(1,1,0,0)->(0,0,0,1)
Find one method! the number is 4
(3,2,1,0)->(2,1,1,1)->(3,1,1,0)->(3,0,0,1)->(3,1,0,0)->(1,1,0,1)->(2,1,1,0)->(0,1,1,1)->(0,2,1,0)->(0,1,0,1)->(0,2,0,0)->(0,0,0,1)
Find one method! the number is 5
(3,2,1,0)->(3,0,1,1)->(3,1,1,0)->(3,0,0,1)->(3,1,0,0)->(1,1,0,1)->(2,1,1,0)->(0,1,1,1)->(0,2,1,0)->(0,0,1,1)->(1,0,1,0)->(0,0,0,1)
Find one method! the number is 6
(3,2,1,0)->(3,0,1,1)->(3,1,1,0)->(3,0,0,1)->(3,1,0,0)->(1,1,0,1)->(2,1,1,0)->(0,1,1,1)->(0,2,1,0)->(0,0,1,1)->(0,1,1,0)->(0,0,0,1)
Find one method! the number is 7
(3,2,1,0)->(3,0,1,1)->(3,1,1,0)->(3,0,0,1)->(3,1,0,0)->(1,1,0,1)->(2,1,1,0)->(0,1,1,1)->(0,2,1,0)->(0,1,0,1)->(1,1,0,0)->(0,0,0,1)
Find one method! the number is 8
(3,2,1,0)->(3,0,1,1)->(3,1,1,0)->(3,0,0,1)->(3,1,0,0)->(1,1,0,1)->(2,1,1,0)->(0,1,1,1)->(0,2,1,0)->(0,1,0,1)->(0,2,0,0)->(0,0,0,1)
Find one method! the number is 9
(3,2,1,0)->(3,1,0,1)->(3,2,0,0)->(3,0,0,1)->(3,1,0,0)->(1,1,0,1)->(2,1,1,0)->(0,1,1,1)->(0,2,1,0)->(0,0,1,1)->(1,0,1,0)->(0,0,0,1)
Find one method! the number is 10
(3,2,1,0)->(3,1,0,1)->(3,2,0,0)->(3,0,0,1)->(3,1,0,0)->(1,1,0,1)->(2,1,1,0)->(0,1,1,1)->(0,2,1,0)->(0,0,1,1)->(0,1,1,0)->(0,0,0,1)
Find one method! the number is 11
(3,2,1,0)->(3,1,0,1)->(3,2,0,0)->(3,0,0,1)->(3,1,0,0)->(1,1,0,1)->(2,1,1,0)->(0,1,1,1)->(0,2,1,0)->(0,1,0,1)->(1,1,0,0)->(0,0,0,1)
Find one method! the number is 12
(3,2,1,0)->(3,1,0,1)->(3,2,0,0)->(3,0,0,1)->(3,1,0,0)->(1,1,0,1)->(2,1,1,0)->(0,1,1,1)->(0,2,1,0)->(0,1,0,1)->(0,2,0,0)->(0,0,0,1)
Find one method! the number is 13
(3,2,1,0)->(2,2,0,1)->(3,2,0,0)->(3,0,0,1)->(3,1,0,0)->(1,1,0,1)->(2,1,1,0)->(0,1,1,1)->(0,2,1,0)->(0,0,1,1)->(1,0,1,0)->(0,0,0,1)
Find one method! the number is 14
(3,2,1,0)->(2,2,0,1)->(3,2,0,0)->(3,0,0,1)->(3,1,0,0)->(1,1,0,1)->(2,1,1,0)->(0,1,1,1)->(0,2,1,0)->(0,0,1,1)->(0,1,1,0)->(0,0,0,1)
Find one method! the number is 15
(3,2,1,0)->(2,2,0,1)->(3,2,0,0)->(3,0,0,1)->(3,1,0,0)->(1,1,0,1)->(2,1,1,0)->(0,1,1,1)->(0,2,1,0)->(0,1,0,1)->(1,1,0,0)->(0,0,0,1)
Find one method! the number is 16
(3,2,1,0)->(2,2,0,1)->(3,2,0,0)->(3,0,0,1)->(3,1,0,0)->(1,1,0,1)->(2,1,1,0)->(0,1,1,1)->(0,2,1,0)->(0,1,0,1)->(0,2,0,0)->(0,0,0,1)
Complete!
16 methods have been found!
ppstay 2003-12-14
  • 打赏
  • 举报
回复
一.【实验题目】
过河问题的求解:三个修道士和三个野人过河,船一次最多只能载两个人,在任何时候修道士的人数不能少于野人人数,否则野人会吃掉修道士。找出六个人顺利过河的所有方案。

二.【实验目的】
通过具体问题的编程求解,了解人工智能的基本解决方法;使用一种搜索策略,以加深理解。

三.【实验内容】
编制程序,使用一定的搜索策略,找出所有过河方法。

四.【设计思想】
1.编程工具
采用C++语言编制控制台程序;
2.整体思想
采用四元组(修道士人数[0~3],会划船野人数[0~2],不会划船野人数[0/1],船所在岸[0/1])描述结点状态,开始状态为(3,2,1,0),目标状态为(0,0,0,1)。采用带回溯的深度优先搜索策略,共定义了7种合法操作{2,0,0},{1,0,0},{1,1,0},{0,1,0},{0,2,0},{0,1,1},{1,0,1}代表上船的人数,根据船所在位置决定在状态上是加或者减操作。扩展结点时按顺序应用操作,知道回溯到初始状态且所有操作用完,程序结束。
3.类设计
state类:描述状态结点,包括描述状态的相关成员变量和操作变量的成员函数
river类:描述和解决过河问题

五.【算法和数据结构】
1.算法
采用带回溯的深度优先策略。
在每个合法结点上应用所有7种操作,生成所有结点,然后判断结点的合法与否,确定是否回溯。每找到一种方法只要没有生成所有结点则回溯继续搜索。直到回溯到初始结点并且初始结点的所有操作已经应用完毕,则整个搜索过程结束。
2.数据结构
采用链表结构,结点是生成的状态,当前结点在链表头。结点中包含状态信息和程序需要的相关控制信息。
新扩展生成的结点放在链表头,回溯时删除头结点并移动头指针。
当找到一种过河方案时,当前链表中的所有结点就是按顺序生成的状态结点,只要遍历链表输出状态就可以得到该种方法经过的状态和所用的操作。
xiaonian_3654 2003-12-14
  • 打赏
  • 举报
回复
隐式图搜索
gaowentao 2003-12-14
  • 打赏
  • 举报
回复
请问传教士和野人问题是什么?
redhat_xu 2003-12-14
  • 打赏
  • 举报
回复
恕小弟不才,

能不能把源文件题目写出来?

64,282

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧