图的深度优先遍历实现农夫过河

                                      数据结构课程设计报告

 

                                                       农夫过河

 

 

 

 

 

 

 

 

                                                                                                                     学号:     xxxxxxxxxx     

                                                                                                                      姓名:          xxx             

                                                                                                                     专业:         xxxxxx         

                                                                                                                     班级:      xxxxxxxxx      

                                                                                                                     指导教师:     xx        

                                                                                                                     完成日期:   2018年6月

 

一、问题描述:

要求设计实现农夫过河问题(农夫带着一只狼,一只羊,一棵白菜,一次只能带一个东西)如何安全过河。

船上一次只能带一个东西,只有农夫会划船。当农夫不在时,狼如果和羊在一起,狼会把羊吃掉,羊不能和白菜在一起,羊会把白菜吃掉。但是狼不吃白菜。试求通过计算,得到能够使农夫,狼,羊,白菜一起安全过河的方法。

 

问题的解决方案:

       可以用栈与队列、深度优先搜索算法及广度优先搜索算法相应的原理去解决问题。

  1. 实现四个过河对象(农夫、白菜、羊和狼)的状态,可以用一个四位二进制数来表示,0表示未过河,1表示已经过河了。
  2. 过河的对象必须与农夫在河的同一侧,可以设计函数来判断。
  3. 防止状态往复,即农夫将一个东西带过去又带回来的情况发生,需将所有可能的状态进行标定。
  4. 可用深度优先搜索算法及广度优先搜索算法去解题。
  5. 在基本要求达到后,可进行创新设计,如系统用户功能控制,改进算法的实现,实现友好的人机交互等等。

 

二、系统设计

 

1.功能实现概括:

       在实现农夫过河中,我采用了无向图的结构来存储结点信息,用邻接矩阵存储结点的关系,用一个四位二进制数来表示过河状态,0表示河北岸,1表示从河南岸,初始状态农夫、狼、羊、白菜都在河北岸,用0000表示。完全过河后用1111表示。

       图的遍历过程采用了深度优先搜素算法,将遍历的过程存入一个数组来记录过河过程,经过系统分析,农夫过河有两种解答方式,由于深度优先算法是遍历所有结点,造成数组部分被覆盖,在第二次遍历时改动了一些算法结构,使得第二种过河方式得以保存实现。

 

 

2.程序功能模块:

       该系统分为三大模块

       第一块:将农夫、狼、羊、白菜作为图的结点元素构建图的结点结构体,构造邻接矩阵,构造图时先判断结点的安全状态,创建只有安全结点,再判断各个结点之间的联系,将有关系的边存入邻接矩阵,构造图的结构。

 

       第二块:利用深度优先搜索算法进行图的遍历,遍历到一个结点时,判断寻找与其有关系的下一个结点,将下一个结点的下标存入设定的ray数组,数组存放的既是过河过程。第二次遍历时,为避免深度优先搜素算法使得存入部分下标被覆盖,在可能被覆盖的结点进行算法改动,将另一种过程存入预定的ray2数组,从而实现两种过河过程。

 

       第三块:分别循环访问ray和ray2数组, 判断数组元素对应的下标结点,打印出对应的过河过程和河两岸的对象状态,最后输出总的过河过程。

 

3.系统流程图

 

(1)图的结构:

       因为从初始状态0000到1111一共有16种情况,判断其安全的情况共有十种,再判断各个结点的连接关系,运用邻接矩阵构建图的结构

(2)流程图:

         略

4.系统的功能调试

 

            本程序不需要用户输入,只需要用户按回车键即可观察下一步的操作即可。通过一定的界面友好的展示给用户正确的过程。

这是第一种过河方式

这是第二种过河方式

两种过河方式在第三步,第四步,第五步有所不同

详细代码如下:

#include  <iostream>
#include  <windows.h>
#include  <stdio.h>
using namespace std;

#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define MAXSIZE 16
#define INFINTITY 65535


int visited[MAXSIZE];
int ray[MAXSIZE];
int ray2[MAXSIZE];
static  int sum =0;
typedef int EdgeType;

/*状态顶点*/
typedef  struct
{
    int farmer;				//农夫 
    int wolf;				//狼 
    int sheep;				//羊 
    int cabbage;			//白菜 
}status;

/*邻接矩阵结点*/
typedef struct
{
    int stanum;             //顶点个数
    status vexs[MAXSIZE];   //储存顶点数组
    EdgeType arc[MAXSIZE][MAXSIZE];  //邻接矩阵权值
}MGraph;

/*判断该状态是否安全*/
int isSafe(int farmer,int wolf,int sheep,int cabbage)
{
	//狼羊同岸 或 羊菜同岸
    if(((farmer!=wolf)&&(wolf==sheep))||((farmer!=sheep)&&(sheep==cabbage)))
        return FALSE;
    else
        return TRUE;
}

/*判断两个点是否有联系*/
int Truemove(MGraph G,int i,int j)
{
    int change = 0;
    if(G.vexs[i].farmer==G.vexs[j].farmer)      //判断农夫是否移动
        return FALSE;
    else if(G.vexs[i].wolf!=G.vexs[j].wolf)		//狼 
                change++;
         if(G.vexs[i].sheep!=G.vexs[j].sheep)	//羊 
                change++;
         if(G.vexs[i].cabbage!=G.vexs[j].cabbage)	//白菜 
                change++;
         if(change>1)
            return FALSE;
         else
            return TRUE;
}

/*创建只有安全结点的图*/
void CreateUDG(MGraph &G)
{
    G.stanum=0;
    //将判断安全的状态存入数组  10种 
    for(int i=0;i<=1;i++)
    {
        for(int j=0;j<=1;j++)
        {
            for(int k=0;k<=1;k++)
            {
                for(int l=0;l<=1;l++)
                {
                   if(isSafe(i,j,k,l))
                   {
                        G.vexs[G.stanum].farmer=i;
                        G.vexs[G.stanum].wolf=j;
                        G.vexs[G.stanum].sheep=k;
                        G.vexs[G.stanum].cabbage=l;
                        G.stanum++;
                   }
                }
            }
        }
    }

    //将有关系的边存入邻接矩阵  构建图的结构 
    for(int i = 0;i < G.stanum;i++)
    {
        for(int j = 0;j< G.stanum;j++)
        {
            if(Truemove(G,i,j))
            {
                G.arc[i][j] = TRUE;
            }
            else
            {
                G.arc[i][j] = INFINTITY;
            }
        }
    }
}

/*邻接矩阵的深度优先递归算法*/
void DFS(MGraph G,int i,int a)
{
	if(a==1)
	{
    	visited[i] = TRUE;
    	//cout<<i<<"  ";
    	//cout<<G.vexs[i].farmer<<G.vexs[i].wolf<<G.vexs[i].sheep<<G.vexs[i].cabbage<<endl;
    	if(i==9)
        	return;
    	for(int j=0;j<G.stanum;j++)
        	if(G.arc[i][j] != INFINTITY  && !visited[j])
        	{
            	ray[i] = j;		
				//cout<<j<<"  ";					
            	DFS(G,j,a);
        	}	
	}
	else if(a==2)
	{
    	visited[i] = TRUE;
    	//cout<<i<<"  ";
    	//cout<<G.vexs[i].farmer<<G.vexs[i].wolf<<G.vexs[i].sheep<<G.vexs[i].cabbage<<endl;
    	if(i==9)
        	return;
    	for(int j=0;j<G.stanum;j++)
        	if(G.arc[i][j] != INFINTITY  && !visited[j])
        	{
        		if(j==1||j==6){
        			continue;
				}
            	ray2[i] = j;
				//cout<<j<<"  ";							
            	DFS(G,j,a);
        	}		
	}

}

/*邻接矩阵的深度优先遍历算法*/
void TraverseDFS(MGraph G,int a)
{
	if(a==1)
	{
	    for(int i = 0;i<G.stanum;i++)
    	{
         	visited[i] = FALSE;
         	ray[i]     = -1;
    	}
    	for(int i=0;i<G.stanum;i++)
        	if(!visited[i])                 //对未访问过的顶点调用DFS 若是连通图的话,只会执行一次
            	DFS(G,i,a);	
	}
	else if(a==2)
	{
	    for(int i = 0;i<G.stanum;i++)
    	{
         	visited[i] = FALSE;
         	ray2[i]     = -1;
    	}
    	for(int i=0;i<G.stanum;i++)
        	if(!visited[i])                 //对未访问过的顶点调用DFS 若是连通图的话,只会执行一次
            	DFS(G,i,a);			
	}

}


/*查找下标*/
int find(MGraph G,int farmer,int wolf,int sheep,int cabbage)
{
    for (int i = 0; i < G.stanum; i++)
    {
        if (G.vexs[i].farmer == farmer && G.vexs[i].wolf == wolf && G.vexs[i].sheep == sheep && G.vexs[i].cabbage == cabbage )
        {
            return i; //返回当前位置
        }
    }
    return -1;
}

/*展示面板*/
void showTable1()       //船在上
{
    cout<<"========================================================================================================================"<<endl;
    cout<<"         <<            船   #                             *                              -  -                           "<<endl;
    cout<<"                           / \\                           * *                               -                            "<<endl;
    cout<<"                           \\ /                                                                                          "<<endl;
    cout<<"         <<                 *                                                            -  -                           "<<endl;
    cout<<"                                                         * *                                                            "<<endl;
    cout<<"                                                          *                              -  -                           "<<endl;
    cout<<"         <<                                              * *                                                            "<<endl;
    cout<<"                                                                                                                        "<<endl;
    cout<<"                                                         * *                              -                             "<<endl;
    cout<<"         <<                                               *                              -  -                           "<<endl;
    cout<<"========================================================================================================================"<<endl;
}
void showTable2()     //船在下
{
    cout<<"========================================================================================================================"<<endl;
    cout<<"         <<                                               *                              -  -                           "<<endl;
    cout<<"                                                         * *                               -                            "<<endl;
    cout<<"                                                                                                                        "<<endl;
    cout<<"         <<-  -                           "<<endl;
    cout<<"                                                         * *                                                            "<<endl;
    cout<<"                                                          *                              -  -                           "<<endl;
    cout<<"         <<                 #                            * *                                                            "<<endl;
    cout<<"                           / \\                                                                                          "<<endl;
    cout<<"                           \\ /                           * *                              -                             "<<endl;
    cout<<"         <<            船   *                             *                              -  -                           "<<endl;
    cout<<"========================================================================================================================"<<endl;
}
void  showPeole1(MGraph G,int i)//北方的状态
{
        cout<<"         北方"<<" ";
        if(G.vexs[i].farmer==0)
            cout<<"\t农夫";
        if(G.vexs[i].wolf==0)
            cout<<"\t狼";
        if(G.vexs[i].sheep==0)
            cout<<"\t羊";
        if(G.vexs[i].cabbage==0)
            cout<<"\t白菜";
        cout<<endl;
}
void  showPeole2(MGraph G,int i)//南方的状态
{
        cout<<"         南方"<<" ";
        if(G.vexs[i].farmer==1)
            cout<<"\t农夫";
        if(G.vexs[i].wolf==1)
            cout<<"\t狼";
        if(G.vexs[i].sheep==1)
            cout<<"\t羊";
        if(G.vexs[i].cabbage==1)
            cout<<"\t白菜";
        cout<<endl;
}

/*加入叙述语句*/
void saySomething(MGraph G,int i,int a)
{
	if(a==1)
	{
    	int wolf = 0, sheep = 0, cabbage = 0;
    	if(sum!=0)
    	{
        	cout<<"\n\n\t第"<<sum<<"步:\t";
        	if(G.vexs[ray[i]].wolf != G.vexs[i].wolf)
        	{
            	if(G.vexs[ray[i]].farmer == 1)
                	cout<<"农 夫 带 狼 去 了 南 边 "<<endl;
            	else
                	cout<<"农 夫 带 狼 去 了 北 边 "<<endl;
        	}
        	else if(G.vexs[ray[i]].sheep != G.vexs[i].sheep)
        	{
            	if(G.vexs[ray[i]].farmer == 1)
                	cout<<"农 夫 带 羊 去 了 南 边 "<<endl;
            	else
                	cout<<"农 夫 带 羊 去 了 北 边 "<<endl;        }
        	else if(G.vexs[ray[i]].cabbage != G.vexs[i].cabbage)
        	{
            	if(G.vexs[ray[i]].farmer == 1)
                	cout<<"农 夫 带 白 菜 去 了 南 边 "<<endl;
            	else
                	cout<<"农 夫 带 白 菜 去 了 北 边 "<<endl;
        	}
        	else
        	{
            	if(G.vexs[ray[i]].farmer == 1)
                	cout<<"农 夫 独 自 去 了 南 边 "<<endl;
            	else
                	cout<<"农 夫 独 自 去 了 北 边 "<<endl;
        	}
    	}
    	sum++;		
	}
	else if(a==2)
	{
    	int wolf = 0, sheep = 0, cabbage = 0;
    	if(sum!=0)
    	{
        	cout<<"\n\n\t第"<<sum<<"步:\t";
        	if(G.vexs[ray2[i]].wolf != G.vexs[i].wolf)
        	{
            	if(G.vexs[ray2[i]].farmer == 1)
                	cout<<"农 夫 带 狼 去 了 南 边 "<<endl;
            	else
                	cout<<"农 夫 带 狼 去 了 北 边 "<<endl;
        	}
        	else if(G.vexs[ray2[i]].sheep != G.vexs[i].sheep)
        	{
            	if(G.vexs[ray2[i]].farmer == 1)
                	cout<<"农 夫 带 羊 去 了 南 边 "<<endl;
            	else
                	cout<<"农 夫 带 羊 去 了 北 边 "<<endl;        }
        	else if(G.vexs[ray2[i]].cabbage != G.vexs[i].cabbage)
        	{
            	if(G.vexs[ray2[i]].farmer == 1)
                	cout<<"农 夫 带 白 菜 去 了 南 边 "<<endl;
            	else
                	cout<<"农 夫 带 白 菜 去 了 北 边 "<<endl;
        	}
        	else
        	{
            	if(G.vexs[ray2[i]].farmer == 1)
                	cout<<"农 夫 独 自 去 了 南 边 "<<endl;
            	else
                	cout<<"农 夫 独 自 去 了 北 边 "<<endl;
        	}
    	}
    	sum++;		
	}

}

/*打印全部操作*/
void sayall(MGraph G,int i,int end,int a)
{
	if(a==1)
	{
		sum = 1;
    	cout<<"\n\n\n第一种总路程为:"<<endl;
    	while(i!=end)
    	{
        	cout<<endl;
        	saySomething(G,i,a);
        	i = ray[i];
    	}
    	getchar();
    	system("cls");
	}
	else if(a==2)
	{
		sum = 1;
    	cout<<"\n\n\n第二种总路程为:"<<endl;
    	while(i!=end)
    	{
        	cout<<endl;
        	saySomething(G,i,a);
        	i = ray2[i];
    	}
		getchar();
    	system("cls");	
	}

}
/*展示总面板*/
void showAll(MGraph G,int start,int end,int a)
{
	if(a==1)
	{
		cout<<"                                                     农夫过河《一》"<<endl<<endl;
		int low = start;
    	while(start!=end)
    	{
        	showPeole1(G,start);		//北 
        	if(G.vexs[start].farmer==0)
            	showTable1();
        	else
            	showTable2();
        	showPeole2(G,start);		//南 

        	saySomething(G,low,a);
        	low = start;
        	
        	start=ray[start];
        	getchar();
        	system("cls");
    	}
		showPeole1(G,start);
		if(G.vexs[start].farmer==0)
    	showTable1();
    	else
    	showTable2();
    	showPeole2(G,low);
    	saySomething(G,low,a);
		
		start=find(G,0,0,0,0);//重置下标
		getchar();
		system("cls");
	}
	else if(a==2)
	{
		cout<<"                                                     农夫过河《二》"<<endl<<endl;		
		sum=0;
		int low = start;
		while(start!=end)
    	{
        	showPeole1(G,start);		//北 
        	if(G.vexs[start].farmer==0)
            	showTable1();
        	else
            	showTable2();
        	showPeole2(G,start);		//南 

        	saySomething(G,low,a);
        	low = start;
        	
        	//cout<<"start="<<start<<endl;//测试遍历过程下标 
        	
        	start=ray2[start];
        	getchar();
        	system("cls");
    	}
		showPeole1(G,start);
		if(G.vexs[start].farmer==0)
    	showTable1();
    	else
    	showTable2();
    	showPeole2(G,start);
    	saySomething(G,low,a);
		
		start=find(G,0,0,0,0);//重置下标
		getchar();
	} 
	
	
}

int main()
{
    MGraph G;
    CreateUDG(G);
    int start = find(G,0,0,0,0);
    int end   = find(G,1,1,1,1);
    TraverseDFS(G,1);	//第一种遍历答案 
    TraverseDFS(G,2);	//第二种遍历答案 
       
    showAll(G,start,end,1);//第一种过河方式 
    sayall(G,start,end,1);//输出第一种过河过程  
    showAll(G,start,end,2);//第二种过河方式 
    sayall(G,start,end,2);//输出第二种过河过程 
    
}

如有错误,欢迎指出。

  • 14
    点赞
  • 77
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值