数据结构 第7章 修道士 实验报告

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

数据结构

实验报告第七章

实验名称:修道士野人问题

实验类型:综合性实验

班级:

学号:

姓名:

实验日期:2014年5月21日

1.问题描述

河的左岸有N个野人和N个修道士以及一条小船,修道士们想用这条小船把所有的人都运到河的右岸,但又受到以下限制:

●修道士和野人都会划船,但船一次只能载C人。

●在任何岸边,为了防止野人侵犯修道士,野人数不能超过修道士数,否

则修道士将会被野人吃掉。

假定野人愿意服从任何一种过河的安排,本设计的主要任务是规划出一种确保修道士安全的过河方案。

2.数据结构设计

用一个三元组(num1,num2,an)表示渡河过程中的各个状态。num1表示左岸上修道士的个数,num2表示左岸上野人的个数,an表示小船位置(0-在右岸上,1-在左岸上)。定义一个结构体,用于存放各个时刻的状态:

typedef struct

{

int num1;//修道士人数

int num2;//野蛮人人数

int an;//表示两岸,0在右岸,1在左岸

}DataType;

用邻接表存储结构实现图的操作,其存储结构为:

typedef struct Node

{

int dest; //邻接表的弧头结点序号

struct Node *next;

}Edge; //邻接表单链表的结点结构体

typedef struct

{

DataType data; //结点数据元素

int sorce; //邻接表的弧尾结点序号

Edge *adj; //邻接边的头指针

int pre; //指向此点的点的序号

}AdjLHeight; //数组的数据元素类型结构体

typedef struct

{

AdjLHeight a[10000]; //邻接表数组

int numOfVerts; /结点个数

int numOfEdges; //边个数

}AdjLGraph; //邻接表结构体

3.算法设计

一侧的野人数目和修道士数目以及船在哪一岸共同构成一种状态,分析一会发现合法的状态是有限且固定的。此时这个问题的求解便类似于寻路问题,已知两个结点和所有节点间的连接关系,求两结点之间的一条路径,简单地进行广度优先搜索即可。

根据给出的小船上的位置数量,生成小船上的安全状态,即在船上的时候修道士的人数也要比野人的数量要多(除非修道士人数为0)。渡船优先规则:左岸一次运走的人越多越好(即左岸运多人优先),同时野人优先运走;右岸一次运走的人越少越好(即右岸运少人优先),同时修道士优先运走。

类似于操作系统中的银行家算法的安全性检测,即让修道士跟野人上船后,检测当船到达对岸后,两岸修道士的安全状态,若修道士安全,则将此结点加入到邻接表中。

采用广度优先搜索,得到一条通路将其输出即可。

部分关键程序:

int findfa(DataType x) //生成在船上修道士仍安全的情况

{

int i=0,a,b,t=0;//从始案到末岸的状态

if(x.an)

{

a=0;b=c-a;

while (a+b>=1)

{

t++;

while (b>=0)

{

fa[i].num1=a;

fa[i].num2=b;

i++;

a++;

b--;

}

a=0;

b=c-a-t;

}

}

else//从末岸到始岸的状态

{

a=1;b=0;t=0;

while (a+b<=c)

{

t++;

while (a>=0)

{

fa[i].num1=a*(-1);

fa[i].num2=b*(-1);

i++;

a--;

b++;

}

a=fa[0].num1*(-1)+t;

b=0;

}

}

return i;

}

int print(AdjLGraph *p,int g) //打印安全渡河的过程

{

DataType b[1000];

int i=0;

while (g!=-1)

{

b[i++]=p->a[g].data;

g=p->a[g].pre;

}

while ((--i)>-1)

{

printf("( %d %d %d )",b[i].num1,b[i].num2,b[i].an);

if (!(b[i].num1==0&&b[i].num2==0&&b[i].an==0))

{

if (b[i].an==1)

printf(" 船上人数[修道士,野人][%d %d] 右边岸上[%d %d

0]\n",b[i].num1-b[i-1].num1,b[i].num2-b[i-1].num2,b[i-1].num1,b[i-1].num2);

else

printf(" 船上人数[修道士,野人][%d %d] 左边岸上[%d %d 1]\n",(b[i].num1-b[i-1].num1)*(-1),(-1)*(b[i].num2-b[i-1].num2),b[i-1].num1,b[i-1].n um2);

}

else

printf("\n");

}

printf("\n");

return 1;

}

void work(AdjLGraph *p) //广度搜索建立表

{

DataType tem;

int i,flag1,g=0,j,count=0,k=0,t;

while (p->a[k].data.an!=-1)

{

j=findfa(p->a[k].data);

for (i=0;i

{

tem.num1=p->a[k].data.num1-fa[i].num1;

tem.num2=p->a[k].data.num2-fa[i].num2;

tem.an=1-p->a[k].data.an;

if (check(tem))

{

flag1=1;

t=k;

while (t!=-1)

{

if(tem.num1==p->a[t].data.num1&&tem.num2==p->a[t].data.num2&&tem.an== p->a[t].data.an)

{

flag1=0;

break;

}

t--;

}

if(flag1==1)

{

g++;

相关文档
最新文档