农夫过河报告最终版Word文件下载.docx
- 文档编号:18677320
- 上传时间:2022-12-31
- 格式:DOCX
- 页数:13
- 大小:62.70KB
农夫过河报告最终版Word文件下载.docx
《农夫过河报告最终版Word文件下载.docx》由会员分享,可在线阅读,更多相关《农夫过河报告最终版Word文件下载.docx(13页珍藏版)》请在冰豆网上搜索。
羊、白菜在左岸还是在右岸,并规定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<
w++)
for(s=0;
S<
s++)
for(v=0;
V<
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<
k;
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)
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<
x3++)
if(COmPare[x3].farmer+COmPare[x3].wolf+COmPare[x3].SheeP+
COmPare[x3].VegetabIe!
=0)
上数与:
%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];
x2++){
SUm=Fwsv.farmer+Fwsv.wolf+Fwsv.sheep+Fwsv.vegetable;
∖n"
for(intx3=0;
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]数组的遍
历,目的是第一轮找出符合条件的值
//这里的if判断是把出现过的值在safe[k]中置零的操作,为了进一步方便判断if(safe[x].farmer==Fwsv.farmer&
safe[x].wolf==Fwsv.wolf&
safe[x].sheep
==Fwsv.sheep&
safe[x].vegetable=0;
//从safe[k]中筛选出农夫状态值与之前相反的并存入COmPare数组中。
因为只有农夫
会划船,所以来回农夫的状态必定改变,比如传进来的是0打头的传输出去的必定是1打头
的。
我们要做的就是从safe[k]中找出农夫状态值与之前相反的数值,总计5个,其中我们
把1111的情况也要剔除掉,现在总计4个了,我们把符合要去的数值从16个缩减到10个
现在又缩减到4个,接下来我们还要缩减
(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&
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并打印我们需要的结果
for(intx3=0;
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]的操作。
不过唯一感到不满意的地方是之前为电脑计算了好多,算法的性能还有待优化。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 农夫 过河 报告 最终版