• 实习六 农夫过河问题


     一、需求分析

    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

              

  • 相关阅读:
    2015生命之旅---第三站象山之行
    我的八年程序之路(四)程序路上的新起点
    2015生命之旅---第二站长沙杭州
    2015生命之旅---第一站重庆
    我的八年程序之路(三)为了理想放弃高薪
    锋友分享:国行和非国行iPhone的送修需知
    iPhone被盗后续更新二:被换机!已取机!没扣住新机!怎么找新机呢?事发半年后跟进...
    iPhone被盗后续更新一:怎么找老机
    iPhone被盗后怎么?这篇文章只办针对iOS7后的系统
    四个小诀窍 告诉你雪景怎么拍才能更好看
  • 原文地址:https://www.cnblogs.com/XDJjy/p/3006024.html
Copyright © 2020-2023  润新知