过河问题实验报告

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

if(a[i][3]==0) printf("farmer ");
if(a[i][0]&&a[i][1]&&a[i][2]&&a[i][3]) printf("none");

printf("
");
printf("west: ");
if(a[i][0]==1) printf("wolf ");
if(a[i][1]==1) printf("goat ");
if (i == -1) { search(Step + 1); }
else if (a[Step][i] == a[Step][3]) {
a[Step + 1][i] = a[Step + 1][3]; search(Step + 1); } } 每次循环从-1 到 2 依次代表农夫渡河时为一人、带狼、带羊、带白菜通过, 利用语句 “b[Step] = i”分别记录每一步中农夫的渡河方式,“a[Step + 1][i] = a[Step + 1][3]”即利用赋值方式使该项与农夫一同到对岸或者回到本岸。若 渡河成功,则依次输出渡河方式。 “i <= 2”即递归操作的界限,当若 i=2 时 仍无符合条件的方式,则渡河失败。
east east east
east east
: farmer goat wolf cabbage west : none
The 1 time
: wolf cabbage
west : farmer goat
------ farmer
: farmer wolf cabbage
west : goat
The 2 time
六、调试过程中的问题
(1)递归循环中,开始时编写 for (i = 0; i <= 3; i++),但当下面写到 a[Step][i] 时发现若 i 从 0 开始则二维数组中每一步都需定义为 a[Step][i-1],给写程序 造成很多不便,同时造成定义混乱,因此修改后将 for 循环定义为 for (i = -1; i <= 2; i++)。 (2)开始运行程序之后,发现程序无法正常运行,开始无显示,经过调试之后 显示乱码,最终发现程序无法正常终止,因为虽然定义了 i 的上限,但并没有定
------ farmer and wolf
: cabbage
west : farmer goat wolf
------ farmer and goat
: farmer goat cabbage
west : wolf
……
east : none
west : farmer goat wolf cabbage
0
0
0
0
成功渡河之后,二维数组存储应为
a[step][0] a[step][1] a[step][2] a[step][3]
1
1
1
1
则有 a[Step][0] + a[Step][1] + a[Step][2] + a[Step][3] == 4。
题目要求狼和羊、羊和白菜不能在一起,即若有下述情况
printf("%s\n",name[b[i] + 1]);
}
}
}
printf("\n\n\n\n");
return;
}
for (i = 0; i < Step; i++)
{
if (memcmp(a[i], a[Step], 16) == 0)//若该步与以前步骤相同,取消操作 { return; } } if (a[Step][1] != a[Step][3] && (a[Step][2] == a[Step][1] || a[Step][0] == a[Step][1])) //若羊和农夫不在一块而狼和羊或者羊和 //白菜在一块,则取消操作 { return; } for (i = -1; i <= 2; i++)//递归,从带第一种开始一次向下循环;同时限定 递归界
0—wolf 1—goat 2—cabbage 3—farmer
将东岸和西岸数字化,,其对应为:
0—东岸
1—西岸
具体对应实例比如在第 3 步之后狼在东岸,羊在西岸,白菜在东岸,农夫在西岸,
则其存储结果为:
a[3][0] a[3][1] a[3][2] a[3][3]
0
1
0
1
故,最初存储状态为
a[0][0] a[0][1] a[0][2] a[0][3]
为 1,输出结果,进入回归步骤
{ for (i = 0; i <=Step; i++)
//能够依次输出不同的方案
{
printf("east: ");
if(a[i][0]==0) printf("wolf ");
if(a[i][1]==0) printf("goat ");
if(a[i][2]==0) printf("cabbage ");
printf("
the %d time\n",i+1);
if(i>0&&i<Step)
{ if (a[i][3] == 0)//农夫在本岸
{
printf("
-----> farmer ");
printf("%s\n",name[b[i] + 1]);
} else//农夫在对岸
{
printf("
<----- farmer ");
在递归的过程中没进行一步都需要判断条件决定是否继续进行此次操作,具 体的判断代码为: (1)if (a[Step][0] + a[Step][1] + a[Step][2] + a[Step][3] == 4)
{…… return} 若该种步骤能使各值均为 1,渡河成功,输出结果,进入回归步骤。 (2)if (memcmp(a[i], a[Step], 16) == 0) { return;} 若该步与以前步骤相同,返回操作。 ( 3 ) if (a[Step][1] != a[Step][3] && (a[Step][2] == a[Step][1] || a[Step][0] == a[Step][1])) {return;} 若羊和农夫不在一块而狼和羊或者羊和白菜在一块,则返回操作。
if(a[i][2]==1) printf("cabbage ");
if(a[i][3]==1) printf("farmer ");
if(!(a[i][0]||a[i][1]||a[i][2]||a[i][3])) printf("none");
printf("\n\n\n");
if(i<Step)
七、课程设计总结
(1)若代码所要实现的功能较多或者程序较为复杂,可先设计好程序的整体框 架,画出流程图,然后依次编写代码分别实现上述功能,最后将各部分代码按照 顺序结合起来,对各个参数稍加调试,便可得到清晰正确的程序。 (2)在用到循环或者递归等算法时,很容易出现对某一界限界定不明导致程序 无法正常运行,而且这些疏漏之处往往是简短几步中不容易发现的,这就需要细 心、耐心地梳理清楚各条脉络,找出问题所在。 (3)在编写程序时,应在方便的情况下尽可能使用同一种变量进行各步的运算, 减少不必要的变量定义,以免造成代码过于混乱。 (4)复杂代码以及大型程序需要小组所有成员共同努力,既可以对同一个问题 进行讨论,找出最简便的实现方式,也可以每个人负责不同的部分,在所有人的 努力下共同创造出一份完整的代码,让它顺利地运行。
a[Step][1] != a[Step][3] && (a[Step][2] == a[Step][1] || a[Step][0] ==
a[Step][1])
则出现错误,应返回操作。
程序采用递归算法,主程序结构的设计为
开始
a[0][0]=0 … … a[0][3]=0
递归
结束
同时定义一维数组 b[N]来存储每一步中农夫是如何过河的。设计程序中实 现递归操作部分的核心代码为 for (i = -1; i <= 2; i++) { b[Step] = i; memcpy(a[Step + 1], a[Step], 16); a[Step + 1][3] = 1 - a[Step + 1][3];
#define N 15
int a[N][4];
int b[N];
char *name[] =
{
"
",
"and wolf",
"and goat",
"and cabbage"
};
void search(int Step)
{
int i; if (a[Step][0] + a[Step][1] + a[Step][2] + a[Step][3] == 4)//若该种步骤能使各值均
int main()
{ printf("\n\n search(0); return 0; }
农夫过河问题,解决方案如下:\n\n\n");
五、测试数据及其结果分析
运行程序可以得到合理的解决方案,共有两种: 带羊到对岸 空手回本岸 带狼到对岸 带羊回本岸 带菜到对岸 空手回本岸 带羊到对岸
带羊到对岸 空手回本岸 带菜到对岸 带羊回本岸 带狼到对岸 空手回本岸 带羊到对岸
(2)变量、函数命名符合规范。
(3)注释详细:每个变量都要求有注释说明用途;函数有注释说明功能,对参
数、返回值也要以注释的形式说明用途;关键的语句段要求有注释解释。
(4)程序的层次清晰,可读性强。
二、 需求分析
1、 题目要求狼和羊、羊和白菜不能单独在一起,涉及对象较多,而且运算 步骤方法较为复杂,要用程序语言实现,需要将具体实例数字化。针对实现整个 过程需要多步,不同步骤中各个事物所处位置不同的情况,可定义一个二维数组 或者结构体来实现对四个对象狼、羊、白菜和农夫的表示。对于东岸和西岸,可 以用 east/west,也可以用 0 或者 1 来表示,以实现在程序设计中的简便性。
义 step 的上限,而在实际中情况的种数是有限的,因此缺少一限制条件,故又 编写限制代码“if (memcmp(a[i], a[Step], 16) == 0)”{return;};这样程 序便能够输出结果。 (3)在只定义二维数组的情况下,因为题目要求输出每次农夫是如何渡河的, 即独自还是带狼、带羊、带白菜,若每次都是比较四个对象位置的变化来确定是 哪个发生了移动则很复杂,因此引入一维数组,用来记录每次移动的对象,这样 在递归操作找出合适的结果之后便可以从记录中一次调出存储的值并将其输出 出来。 (4)在找出成功渡河方案便终止递归操作的情况下,只有一种结果输出,而认 为判断有至少两种结果,因此代码有明显缺陷,为解决这一问题,在试探方案成 功之后,返回到循环体中,继续进行下一步循环,这样就保证了程序的完整全面, 最终得到两种解决方案。
过河问题
一、 课题内容和要求
1、本课题要求出完整程序,能够解决下面的问题: 一个农夫带着一只羊,一条狼和一颗白菜想从河的东岸到西岸去。河上仅有
一条船。假设他每次只能带一只羊,或者一条狼,或者一颗白菜过河,并且当人 不在场时,狼和羊,或羊和白菜不能单独在一起。试编写程序求出他带一只羊, 一条狼和一颗白菜过河的办法。 2、题目要求如下: (1)不需要从键盘读入数据。结果输出时,为便于观察,以文字的形式输出过 河的全过程,列出所有可能的过河过程。格式如下:
递归部分程序结构为
search(step) (step) (step)
输出
解决
Y
方案
Y
return
Y
N
结束
人、狼、羊、白 菜、全部在西岸?
N
狼和羊、羊和白 菜单独在一起?
N
该状态与前 面相同?
N
i=-1
i<=-2?
Y
i++
search(step+1)
四、源程序代码
#include <stdio.h> #include <stdlib.h> #include <string.h>
限 { b[Step] = i; memcpy(a[Step + 1], a[Step], 16);//复制上一步状态,进行下一步移动 a[Step + 1][3] = 1 - a[Step + 1][3];//农夫过去或者回来 if (i == -1) {
search(Step + 1);//进行第一步 } else if (a[Step][i] == a[Step][3])//若该物与农夫同岸,带回 { a[Step + 1][i] = a[Step + 1][3];//带回该物 search(Step + 1);//进行下一步 } } }
4、输出界面要求具有每一步中农夫所带对象及每步之后各岸的物体,需要定 义不同的数组来分别存储上述内容,并使界面所示方案清晰简洁。
三、 概要设计
本程序使用递归算法,为了方便将各个实例数字化。定义二维数组
int a[N][4] 存储每一步中各个对象所处的位置,用 0-3 分别表示二维数组的一
维下标。具体对应为:
2、题目要求给出四种事物的过河步骤,没有对先后顺序进行约束,这就需 要给各个事物依次进行编号,然后依次试探,若试探成功,进行下一步试探。这 就需要使用循环或者递归算法,避免随机盲目运算且保证每种情况均试探到。
3、题目要求求出农夫带一只羊,一条狼和一颗白菜过河的办法,所以依次 成功返回运算结果后,需要继续运算,直至求出结果,即给出农夫的过河方案。
相关文档
最新文档