农夫过河报告最终版.docx

上传人:b****5 文档编号:5690228 上传时间:2022-12-31 格式:DOCX 页数:13 大小:62.70KB
下载 相关 举报
农夫过河报告最终版.docx_第1页
第1页 / 共13页
农夫过河报告最终版.docx_第2页
第2页 / 共13页
农夫过河报告最终版.docx_第3页
第3页 / 共13页
农夫过河报告最终版.docx_第4页
第4页 / 共13页
农夫过河报告最终版.docx_第5页
第5页 / 共13页
点击查看更多>>
下载资源
资源描述

农夫过河报告最终版.docx

《农夫过河报告最终版.docx》由会员分享,可在线阅读,更多相关《农夫过河报告最终版.docx(13页珍藏版)》请在冰豆网上搜索。

农夫过河报告最终版.docx

农夫过河报告最终版

这最起码是一个报告,虽然我尽力的看,终究还是看不懂。

农夫过河算法实验报告

――数据结构项目课研究课题

组长:

崔俊

组员:

李琦、郑鸿飞、王琅辉、张育博

15.12.29

摘要

农夫过河问题是应用广度优先搜索和深度优先搜索的典型问题,但这里我们应用了简单

的数组,通过层层筛选的手段也解决了同样的问题,其中用到了部分广度优先搜索的思想。

、八■、-

前言

农夫过河问题描述:

一个农夫带着一只狼、一只羊和一棵白菜,身处河的南岸。

他要把这些东西全部运到北岸。

他面前只有一条小船,船只能容下他和一件物品,另外只有农夫才

能撑船。

如果农夫在场,则狼不能吃羊,羊不能吃白菜,否则狼会吃羊,羊会吃白菜,所以农夫不能留下羊和白菜自己离开,也不能留下狼和羊自己离开,而狼不吃白菜。

请求出农夫

将所有的东西运过河的方案。

正文

1∙问题抽象和数据组织

农夫过河问题应该应用图的广度优先遍历或者深度优先遍历,但这里我们仅使用简单的

线性表一一数组,通过多重的条件限制,达成目的。

这里我们同样用O和1代表农夫、狼、

羊、白菜在左岸还是在右岸,并规定O在左,1在右,我们的目的便是从OOOO通过一系列变换到1111。

2.农夫过河算法源代码

#ineludeVStdio.h>

#defineMAX16

typedefStrUCtFWSV

{

intfarmer;

intwolf;

intsheep;

intvegetable;

}Item;

//函数原型

//操作:

筛选符合条件的安全的数组成员

//操作前:

//操作后:

返回安全数组的指针

voidSCreen(void);

//操作:

判断下一个数应该取安全数组中那个数

//操作前:

传递一个结构体数组成员

//操作后:

返回另一个结构体数组指针

Item*judge(ItemFwsv);

Itemsafe[MAX];

intk=0;

intmain(Void)

{

SCreen();

Item*next;

Itemfirst,secOnd,end;

first=safe[0];

end=safe[k];

Printf("first:

0000\n");next=judge(first);

voidSCreen(void)

{

intf=0,w=0,s=0,v=0;

for(f=0;f<2;f++)

{

for(w=0;W<2;w++)

{

for(s=0;S<2;s++)

{

for(v=0;V<2;v++)

{

if(!

(f!

=S&&(S==WIlS==V)))

{

safe[k].farmer=f;

safe[k].wolf=w;

safe[k].sheep=s;

safe[k].vegetable=v;

k++;

}

}

}

}

}

}

Item*judge(ItemFWSV)

{

Item*next;

ItemCOmPare[4];

next=compare;

intx1=0;

intSUm=0;

if(Fwsv.farmer==0)

{

for(intX=0;X

{

ZZ把出现过的置零操作

if(safe[x].farmer==Fwsv.farmer&&safe[x].wolf==Fwsv.wolf&&

safe[x].sheep==Fwsv.sheep&&safe[x].vegetable==Fwsv.vegetable)

{

safe[x].farmer=0;

safe[x].wolf=0;

safe[x].sheep=0;safe[x].vegetable=0;

}

ZZ筛选出农夫状态值与之前相反的1变00变1

if(safe[x].farmer==1&&(safe[x].farmer+safe[x].wolf+

safe[x].sheep+safe[x].vegetable!

=4))

{

COmPare[x1]=safe[x];

x1++;

}

}

for(intx2=0;x2<4;x2++)

//删除状态值与农夫不同但是改变了的

SUm=Fwsvfarmer+Fwsv.wolf+Fwsv.sheep+Fwsv.vegetable;

if((FWSV.farmer!

=Fwsv.wolf&&COmPare[x2].wolf!

=Fwsv.wolf)

||(Fwsv.farmer

!

=Fwsv.sheep

&&COmPare[x2].SheeP

!

=

Fwsv.sheep)

Il

(Fwsv.farmer

!

=Fwsv.vegetable

&&COmPare[x2].VegetabIe

!

=

Fwsv.vegetable)

Il

(Fwsv.farmer

!

=Fwsv.vegetable

&&COmPare[x2].VegetabIe

!

=

Fwsv.vegetable))

{

COmPare[x2].farmer=0;

COmPare[x2].wolf=0;

COmPare[x2].SheeP=0;

COmPare[x2].VegetabIe=0;

}

sum+=2;

//对和的限制

if(compare[x2].farmer+COmPare[x2].wolf+COmPare[x2].SheeP+

COmPare[x2].VegetabIe!

=SUm)

{

COmPare[x2].farmer=0;

COmPare[x2].wolf=0;

COmPare[x2].SheeP=0;

COmPare[x2].VegetabIe=0;

}

}

Printf("∖n");

for(intx3=0;x3<4;x3++)

{

if(COmPare[x3].farmer+COmPare[x3].wolf+COmPare[x3].SheeP+

COmPare[x3].VegetabIe!

=0)

{

Printf("上数与:

%d%d%d%d连∖n",

ComPare[x3].farmer,compare[x3].wolf,compare[x3].sheep,compare[x3].vegetabl);

}

if(Fwsv.farmer==1)

{

for(inty=0;yVk;y++)

{

if(safe[y].farmer==Fwsv.farmer&&safe[y].wolf==Fwsv.wolf&&safe[y].sheep==Fwsv.sheep&&safe[y].vegetable==Fwsv.vegetable)

{

safe[y].farmer=0;

safe[y].wolf=0;

safe[y].sheep=0;safe[y].vegetable=0;

}

if(safe[y].farmer==0&&(safe[y].farmer+safe[y].wolf

safe[y].sheep+safe[y].vegetable!

=0))

{

ComPare[x1]=safe[y];

x1++;

}

}

for(intx2=0;x2<4;x2++){

SUm=Fwsv.farmer+Fwsv.wolf+Fwsv.sheep+Fwsv.vegetable;

if((FWSV.farmer!

=Fwsv.wolf&&COmPare[x2].wolf!

=Fwsv.wolf)

Fwsv.sheep)

Fwsv.vegetable)

Fwsv.vegetable))

{

COmPare[x2].farmer=0;

COmPare[x2].wolf=0;

COmPare[x2].SheeP=0;

COmPare[x2].VegetabIe=0;

}

∖n");

}

Printf("for(intx3=0;x3<4;x3++)

if(ComPare[x3].farmer+ComPare[x3].Wolf+ComPare[x3].SheeP+

ComPare[x3].VegetabIe!

=0)

{

Printf("上数与:

%d%d%d%d连∖n",

ComPare[x3].farmer,compare[x3].wolf,compare[x3].sheep,compare[x3].vegetable

);

}

}

}

returnnext;

}

3.算法功能说明和流程描述

首先我们定义了一个结构体Item

typedefStrUCtFWSV

{

intfarmer;

intwolf;

intsheep;

intvegetable;

}Item;

Item中包含了农夫(farmer),狼(wolf),羊(SheeP),白菜(VegetabIe),用来表示农夫、狼、羊、白菜的状态,并作出规定当为0的时候表示在左岸,当为1的时候表示

在右岸,我们的目标便是从0000的状态到1111的状态。

接下来用一个调用函数SCreen()

voidSCreen(void)

{

intf=0,w=0,s=0,v=0;

for(f=0;f<2;f++)

{

for(w=0;W<2;w++)

{

for(s=0;S<2;s++)

{

for(v=0;V<2;v++)

{

if(!

(f!

=S&&(S==WIlS==V)))

safe[k].farmer=f;

safe[k].wolf=w;

safe[k].sheep=s;

safe[k].vegetable=v;

k++;

}

}

}

}

}

}

函数一连用了4个for循环完成了对0000到1111之间每一位数字的所有排列组合的遍历,虽然这里的时间复杂度直接跃至0(n4)但却是比较全面、写法简单的遍历,而且n仅为

2,其中的if语句的判断从所有的排列组合中(总计16种)剔除了不会出现的组合,其中包括:

农夫不在,羊吃白菜,狼吃羊等情况。

并让符合条件的情况存入了全局变量数组safe[MAX]中。

Item*judge(ltemFWSV)函数是整个算法的核心,思想比较简单但写法繁琐,目的是

判断safe[k]数组中符合如题条件的数值,它的参数是上一次的状态值,对于初始时便为0000,它的返回值是一个符合条件的数值的数组首地址next,为了防止有多解的情况我们

把符合条件的值存入了一个COmPare[4]数组,如果为单解则将COmPare中其他成员置零,

接下来我们拆分着看看这个函数。

if(Fwsv.farmer==0)表示农夫现在在左岸接下来的for循环是对safe[k]数组的遍

历,目的是第一轮找出符合条件的值

for(intX=0;X

{

//这里的if判断是把出现过的值在safe[k]中置零的操作,为了进一步方便判断if(safe[x].farmer==Fwsv.farmer&&safe[x].wolf==Fwsv.wolf&&safe[x].sheep

==Fwsv.sheep&&safe[x].vegetable==Fwsv.vegetable)

{

safe[x].farmer=0;

safe[x].wolf=0;

safe[x].sheep=0;

safe[x].vegetable=0;

}

//从safe[k]中筛选出农夫状态值与之前相反的并存入COmPare数组中。

因为只有农夫

会划船,所以来回农夫的状态必定改变,比如传进来的是0打头的传输出去的必定是1打头

的。

我们要做的就是从safe[k]中找出农夫状态值与之前相反的数值,总计5个,其中我们

把1111的情况也要剔除掉,现在总计4个了,我们把符合要去的数值从16个缩减到10个

现在又缩减到4个,接下来我们还要缩减

if(safe[x].farmer==1&&(safe[x].farmer+safe[x].wolf+safe[x].sheep+safe[x].vegetable!

=4))

{

COmPare[x1]=safe[x];

x1++;

}

}

ZZ这里的for便是对COmPare的遍历了

for(intx2=0;x2<4;x2++)

{

ZZ上述缩减到4个但是范围还是太大,现在置零状态值与农夫不同但是改变了的。

SUm=Fwsv.farmer+Fwsv.wolf+Fwsv.sheep+Fwsv.vegetable;

if((FWSV.farmer!

=Fwsv.wolf&&COmPare[x2].wolf!

=Fwsv.wolf)

II(FWSV.farmer!

=Fwsv.sheep&&COmPare[x2].SheeP!

=Fwsv.sheep)

Il(Fwsv.farmer!

=Fwsv.vegetable&&COmPare[x2].VegetabIe

Il(Fwsv.farmer!

=Fwsv.vegetable&&COmPare[x2].VegetabIe

COmPare[x2].farmer=0;

COmPare[x2].wolf=0;

COmPare[x2].SheeP=0;

COmPare[x2].VegetabIe=0;

}

sum+=2;

ZZ由于船一次只能拉不超过两个,其中一个还要是农夫划船,所以这里我们对和有一个

限制。

当农夫拉着东西从左岸划向右岸时,总的状态值之和应该等于上一个状态+现在的状

态,而现在的状态和必定为2,所以sum+=2这里我们举个例子就明白了:

0000开始,农夫

拉着羊从左岸到右岸变成1010(此时的状态和为2),之后农夫划船回来变成0010(此时

状态值为1),接着农夫划船拉着狼从左至右变成1110(此时状态和为3,3=1+2)......

if(Compare[x2].farmer+COmPare[x2].wolf+COmPare[x2].SheeP+

COmPare[x2].VegetabIe!

=SUm){

COmPare[x2].farmer=0;

COmPare[x2].wolf=0;

COmPare[x2].SheeP=0;

COmPare[x2].VegetabIe=0;

}

}

Printf("∖n");

ZZ通过上述三种限制,我们已经可以判断出safe[k]中完全符合要求的数值了,可能有

一个,可能有两个,也可能多个,接下来的for遍历COmPare并打印我们需要的结果

for(intx3=0;x3<4;x3++)

{

if(COmPare[x3].farmer+COmPare[x3].wolf+COmPare[x3].SheeP+COmPare[x3].VegetabIe!

=0)

{

Printf("上数与:

%d%d%d%d连\n",

ComPare[x3].farmer,compare[x3].wolf,compare[x3].sheep,compare[x3].vegetabl

}

}

}

if(Fwsv.farmer==1)

{

/*表示农夫现在在右岸接下来的for循环是对safe[k]数组的遍历,目的是第一轮找出

符合条件的值,与Fwsv.farmer==0的情况一样,判断方法与条件也完全相同,只不过对

于0打头的情况省去了对和的限制这一条件*/

}

4.算法实现与验证

fiiat:

WW*

j⅞Q⅜⅛现争值取鎬同

L數与:

on≠∣SA

■■■■

Lt⅛⅛ιWIL+B⅛

ri⅛⅜g⅛

上對环OooLW

Um*呷__

上罷芍;DLDItR⅛

上融与:

lll⅛t⅛⅛

SELdlUl-

Plesa-IIIyke⅛r1,口二口CtiIiLI蓉

首先0000传入judge函数,返回1010,表示0000与1010相连,接下来1010传入,返回0010,现在0000----1010----0010,接下来0010传入,返回1011和1110两个,表示0000----1010----0010----1011和1110,我们只取第一个,1011传入,返回0001,传入0001,返回1101,现在是OOOO----1010----0010----1011(还有1110)----0001----1101,接下来传入1101,返回0100和0101,同理只取第一个,传入0100,返回1110,至此结束整个传递,到达1111的状态

这些数字看着有些不清晰,我们来整理下

0000——1010一0010-—-1011——0001——Iol-——0100

OlOI

整理得

OOOOIOIo一0010—IOr——OoOI——1010101—1111

OIOO-^

通过图示我们发现农夫过河有两种解

(1)农夫、狼、羊、白菜开始都在左岸0000,农夫拉羊从左岸到右岸1010,农夫自己从右岸到左岸0010,农夫拉着白菜从左岸到右岸1011,农夫把羊从右岸拉回左岸0001,农夫拉着狼从左岸到右岸1101,农夫自己从右岸到左岸0101,农夫拉着羊从左岸到右岸1111。

(2)农夫、狼、羊、白菜开始都在左岸0000,农夫拉羊从左岸到右岸1010,农夫自己

从右岸到左岸0010,农夫拉着狼从左岸到右岸1110,农夫把羊从右岸拉回左岸0100,农夫

拉着白菜从左岸到右岸1101,农夫自己从右岸回到左岸0101,农夫拉着羊从左岸到右岸

1111。

5.算法性能分析

本算法性能比较低,因为是一次次遍历,筛选,最后确定符合条件的值。

但算法偏向正

常思维,较简单,且节省了很大内存,整个过程均建立在对safe[k]数组和ComPare[k]的操作。

不过唯一感到不满意的地方是之前为电脑计算了好多,算法的性能还有待优化。

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 医药卫生 > 基础医学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1