农夫过河报告最终版.docx
《农夫过河报告最终版.docx》由会员分享,可在线阅读,更多相关《农夫过河报告最终版.docx(13页珍藏版)》请在冰豆网上搜索。
农夫过河报告最终版
这最起码是一个报告,虽然我尽力的看,终究还是看不懂。
农夫过河算法实验报告
――数据结构项目课研究课题
组长:
崔俊
组员:
李琦、郑鸿飞、王琅辉、张育博
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)
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变1if(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].wolfsafe[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.算法功能说明和流程描述首先我们定义了一个结构体ItemtypedefStrUCtFWSV{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].VegetabIeIl(Fwsv.farmer!=Fwsv.vegetable&&COmPare[x2].VegetabIeCOmPare[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⅛上對环OooLWUm*呷__上罷芍;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-——0100OlOI整理得OOOOIOIo一0010—IOr——OoOI——1010101—1111OIOO-^通过图示我们发现农夫过河有两种解(1)农夫、狼、羊、白菜开始都在左岸0000,农夫拉羊从左岸到右岸1010,农夫自己从右岸到左岸0010,农夫拉着白菜从左岸到右岸1011,农夫把羊从右岸拉回左岸0001,农夫拉着狼从左岸到右岸1101,农夫自己从右岸到左岸0101,农夫拉着羊从左岸到右岸1111。(2)农夫、狼、羊、白菜开始都在左岸0000,农夫拉羊从左岸到右岸1010,农夫自己从右岸到左岸0010,农夫拉着狼从左岸到右岸1110,农夫把羊从右岸拉回左岸0100,农夫拉着白菜从左岸到右岸1101,农夫自己从右岸回到左岸0101,农夫拉着羊从左岸到右岸1111。5.算法性能分析本算法性能比较低,因为是一次次遍历,筛选,最后确定符合条件的值。但算法偏向正常思维,较简单,且节省了很大内存,整个过程均建立在对safe[k]数组和ComPare[k]的操作。不过唯一感到不满意的地方是之前为电脑计算了好多,算法的性能还有待优化。
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)
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)
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];
for(intx2=0;x2<4;x2++){
SUm=Fwsv.farmer+Fwsv.wolf+Fwsv.sheep+Fwsv.vegetable;
∖n");
Printf("for(intx3=0;x3<4;x3++)
if(ComPare[x3].farmer+ComPare[x3].Wolf+ComPare[x3].SheeP+
ComPare[x3].VegetabIe!
ComPare[x3].farmer,compare[x3].wolf,compare[x3].sheep,compare[x3].vegetable
);
returnnext;
3.算法功能说明和流程描述
首先我们定义了一个结构体Item
Item中包含了农夫(farmer),狼(wolf),羊(SheeP),白菜(VegetabIe),用来表示农夫、狼、羊、白菜的状态,并作出规定当为0的时候表示在左岸,当为1的时候表示
在右岸,我们的目标便是从0000的状态到1111的状态。
接下来用一个调用函数SCreen()
函数一连用了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].VegetabIeIl(Fwsv.farmer!=Fwsv.vegetable&&COmPare[x2].VegetabIeCOmPare[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⅛上對环OooLWUm*呷__上罷芍;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-——0100OlOI整理得OOOOIOIo一0010—IOr——OoOI——1010101—1111OIOO-^通过图示我们发现农夫过河有两种解(1)农夫、狼、羊、白菜开始都在左岸0000,农夫拉羊从左岸到右岸1010,农夫自己从右岸到左岸0010,农夫拉着白菜从左岸到右岸1011,农夫把羊从右岸拉回左岸0001,农夫拉着狼从左岸到右岸1101,农夫自己从右岸到左岸0101,农夫拉着羊从左岸到右岸1111。(2)农夫、狼、羊、白菜开始都在左岸0000,农夫拉羊从左岸到右岸1010,农夫自己从右岸到左岸0010,农夫拉着狼从左岸到右岸1110,农夫把羊从右岸拉回左岸0100,农夫拉着白菜从左岸到右岸1101,农夫自己从右岸回到左岸0101,农夫拉着羊从左岸到右岸1111。5.算法性能分析本算法性能比较低,因为是一次次遍历,筛选,最后确定符合条件的值。但算法偏向正常思维,较简单,且节省了很大内存,整个过程均建立在对safe[k]数组和ComPare[k]的操作。不过唯一感到不满意的地方是之前为电脑计算了好多,算法的性能还有待优化。
//这里的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].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!
ZZ这里的for便是对COmPare的遍历了
ZZ上述缩减到4个但是范围还是太大,现在置零状态值与农夫不同但是改变了的。
II(FWSV.farmer!
=Fwsv.sheep&&COmPare[x2].SheeP!
=Fwsv.sheep)
Il(Fwsv.farmer!
=Fwsv.vegetable&&COmPare[x2].VegetabIe
ZZ由于船一次只能拉不超过两个,其中一个还要是农夫划船,所以这里我们对和有一个
限制。
当农夫拉着东西从左岸划向右岸时,总的状态值之和应该等于上一个状态+现在的状
态,而现在的状态和必定为2,所以sum+=2这里我们举个例子就明白了:
0000开始,农夫
拉着羊从左岸到右岸变成1010(此时的状态和为2),之后农夫划船回来变成0010(此时
状态值为1),接着农夫划船拉着狼从左至右变成1110(此时状态和为3,3=1+2)......
if(Compare[x2].farmer+COmPare[x2].wolf+COmPare[x2].SheeP+
=SUm){
ZZ通过上述三种限制,我们已经可以判断出safe[k]中完全符合要求的数值了,可能有
一个,可能有两个,也可能多个,接下来的for遍历COmPare并打印我们需要的结果
if(COmPare[x3].farmer+COmPare[x3].wolf+COmPare[x3].SheeP+COmPare[x3].VegetabIe!
%d%d%d%d连\n",
ComPare[x3].farmer,compare[x3].wolf,compare[x3].sheep,compare[x3].vegetabl
)
/*表示农夫现在在右岸接下来的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