实习六 农夫过河问题

 一、需求分析

1.问题描述:

一个农夫带着一只狼、一只羊和一棵白菜,身处河的南岸。他要把这些东西全部运到北岸。他面前只有一条小船,船只能容下他和一件物品,另外只有农夫才能撑船。如果农夫在场,则狼不能吃羊,羊不能吃白菜,否则狼会吃羊,羊会吃白菜,所以农夫不能留下羊和白菜自己离开,也不能留下狼和羊自己离开,而狼不吃白菜。

2.基本要求:                        

(1)利用图的存储结构

(2)图的搜索算法

(3)求出农夫将所有的东西运过河的所有方案    

 6.农夫过河问题

一、需求分析

1.问题描述:

一个农夫带着一只狼、一只羊和一棵白菜,身处河的南岸。他要把这些东西全部运到北岸。他面前只有一条小船,船只能容下他和一件物品,另外只有农夫才能撑船。如果农夫在场,则狼不能吃羊,羊不能吃白菜,否则狼会吃羊,羊会吃白菜,所以农夫不能留下羊和白菜自己离开,也不能留下狼和羊自己离开,而狼不吃白菜。

2.基本要求:                        

(1)利用图的存储结构

(2)图的搜索算法

(3)求出农夫将所有的东西运过河的所有方案    

          

二、设计

      1. 设计思想

    (1)存储结构

         以邻接矩阵存储合理状态,用一个一维数组保存所有的方案;

(2)主要算法基本思想

       人,狼,羊和白菜共有2的四次方16种状态(河岸的状态可由人的状态确定),去掉不允许出现的6种状态,10个状态对应矩阵的10个结点值,然后根据状态的连续改变初始化矩阵,接着就用递归的深度优先法搜索所有的路径,即求出过河的方案。

main

 

    2. 设计表示

        (1)函数调用关系图

    main→Judge→Initiate→DFS→Push→StackPop→Top→GetTop→           printfpath→Ch

 
   

  (2)函数接口规格说明

int Judge(int a,int b)  //将16种状态通过a,b输入,去掉不允许的6种

int GetTop(Path *path,int *m)   //出栈

int Push(Path *path,int m)      //入栈

int Top(Path *path ,int *m)    //读出栈顶值

void Initiate(AdjMGraph *G,int n)//邻接矩阵顶点数为n的邻接矩阵G的建立

int DFS(AdjMGraph *G,Path *path,int x,int t) 图G中搜索的起始点为X,从t点开始搜索与x关联的顶点,搜索过的点入栈path。

int printfpath(Path *path)    //复制出出栈path中所有值,用FA【】保存

void Printf(AdjMGraph *G)//辅助:邻接矩阵输出,用于观察搜索的过程。

void Ch(int i) //将状态转换为汉字的方案输出

3. 详细设计(主要函数)  

【1】int Judge(int a,int b)

将十进制的16种状态分别转换为二进制的数存在一维数组中

   判断:

       人不在时,羊狼,羊菜不能再一起

从而初始化了矩阵的结点值

【2】Initiate(&graph,k);

通过Judge函数判断可以连续变化的状态

   在Judge中人的状态必须一次一遍,而其他东西的状态,最多变一个。根据其返回值将矩阵初始化。

【3】DFS(AdjMGraph *G,Path *path,int x,int t)

递归的深度优先搜索法

int a=0;//遍寻下一条路径

int DFS(AdjMGraph *G,Path *path,int x,int t)

{

       int i;

       int k,p,m;

        Push(path,x);//遍历过的点入栈

        p=0;

       k=0;          //路径未遍历完

       for(i=t;i<N;i++) //搜相关联的顶点

       if(G->edge[i][x]>0)

      {

          k=1;

          G->edge[i][x]=0;

          G->edge[x][i]=0; //此边已访问,删除此边

          DFS(G,path,i,0);//找到的是与x关联的i,寻找下一条关联的边

          break;

      }

       if(k==0)       //遍历完当前顶点关联的边

       {

              printfpath(path);                                                              

                       while(path->top!=0&&p==0&&a<N-1)//a为点数减1

              {

                                GetTop(path,&m);                                

             Top(path,&x);                                                                           for(i=0;i<N;i++)

             if(G->edge[i][x]>0)

                          {

                                p=1;

                                k=1;                   //一条路径未遍历完

                                if(x==0)               //从新开始遍历

                                {

                                    G->edge[x][m]=1;

                                    G->edge[m][x]=1;

                                    GetTop(path,&x);

                   }

                  G->edge[x][m]=1;G->edge[m][x]=1;

                            a=++m;//如果可能的话,从当前节点的下一条关联边开始搜寻

              GetTop(path,&x);

                                DFS(G,path,x,a);//x被入栈

                                break;

                          }                                           

                      G->edge[x][m]=1;G->edge[m][x]=1;//恢复在上一层中被删除的边

                       }

       }

       return 0;

}

三、调试分析

      1.调试过程中遇到的主要问题是如何解决的;

      该题有两大难点,一是:矩阵的合理逻辑构建

                      二是:两条方案的搜出

       刚开始由于平常做ACM题图论的影响,没有正确把握题意,曲解了题意,在老师的提示下正确的理解了题意。

       由于搜图函数已在理解错误下正确写出,所以分析了如何逻辑构图之后,问题很容易就得到解决。在老师的指导下,程序越来越完善。   

2.对设计和编码的回顾讨论和分析;

在遇到每个问题的时候,一定要认真冷静的分析题意,以免通过过往经验而误读题意,最后导致与正确结果南辕北辙的后果。

弄懂题意后,要先从程序的整体入手,分析写程序的难点所在,然后联系所学找到可能解决的途径,选出最佳的方法攻破难点。

最后还等考虑程序的安全性,尤其是健壮性的问题,使程序更加的完善,如有可能最好能解决题目之外类似的问题。

3.时间和空间复杂度的分析;

【1】:图的初始化算法 时间O(n*n),空间O(1)

       【2】:图的搜索算法 时间O(n*n),  空间O(1)

      4.改进设想;

       程序能实现预期功能,可有改进空间

【1】:图更简洁初始化方法

       【2】:更能解决一般性的问题

5.经验和体会等。

多参加有益的比赛,科研,动手编程,才能熟练灵活的掌握C语言基础知识,才能更好的理解掌握数据结构的精髓。从而避免基础语法错误,让代码变得更简洁高效。如此才能准确高效的解决问题。

四、用户手册(即使用说明)

   仅需按照提示的输入即可。若出错,则重新来过。

五、运行结果

运行环境:codeblocks

测试用表:1 2 3 4

          0 1 2 3

          1 2 2 3

运行后的界面

测试数据:1 2 3 4

**输入不符合要求或不满足题意时,无法输出正确结果

****在输入完后,核对输入是否符合题意,如若不然提示出错,重新输入

(已改正)测试数据:1 2 3 4

正确测试数据:1 2 2 3

六、源程序清单

https://wenku.baidu.com/view/7263c7048ad63186bceb19e8b8f67c1cfbd6ee39

          

原文地址:https://www.cnblogs.com/XDJjy/p/3006024.html