农夫过河

#include "iostream"
using namespace std;
#define  Max 20                            //最大顶点数  

typedef struct                              //图顶点类型
{
	 int R,H,T,C;                           
}Ding; 

typedef struct                              //图结点类型
{
	 int DingS;                             //顶点个数
	 Ding DXL[Max];                         //顶点向量
	 int Matrix[Max][Max];                  //图的邻接矩阵用于存储图的边,矩阵元素个数取决于顶点个数
}Tu; 
int flags[Max];                             //标志数组
int path[Max];                              //存储路径数组

void Init(int A[])                          //初始化标志数组函数
{
	 int i;
	 for(i = 0;i < Max;i++)                 //标志数组置0
	 {
		 flags[i] = 0;
	 }
}
int Search(Tu *G,int R,int H,int T,int C)   //查找顶点(R,L,Y,C)在顶点向量中的位置函数
{  
	 int i;
	 for(i = 0;i < G->DingS;i++)
	 {
	  if(G->DXL[i].R == R && G->DXL[i].H == H && G->DXL[i].T == T && G->DXL[i].C == C)
		 return i;                          //存在则返回当前位置
	 }
	 return -1;                             //没有找到此顶点
}
int Safety(int R,int H,int T,int C)         //判断目前的(R,L,Y,C)是否安全函数
{
	 if(R != T && (H == T || T == C))       //农夫与羊不在一起且狼与羊或羊与白菜在一起时不安全,返回0
		 return 0; 
	 else                                    
		 return 1;                          //安全时返回1 
}
int PassRiver(Tu *G,int i,int j)            //判断状态i与状态j之间是否可交换函数
{
	 int k = 0;
	 //以下三个条件不同时满足两个且农夫状态改变时可交换,即农夫每次只能带一件东西过河
	 if(G->DXL[i].H != G->DXL[j].H)
		 k++;
	 if(G->DXL[i].T != G->DXL[j].T)
		 k++;
	 if(G->DXL[i].C != G->DXL[j].C)
		 k++;
	 if(G->DXL[i].R != G->DXL[j].R && k <= 1)
		return 1;                          //可交换时
	 else 
		return 0;                          //不可交换时
}
Tu *Create(Tu *G)                       //生成图的邻接矩阵及顶点向量函数
{
	 int i = 0,j,R,H,T,C;
	 for(R=0;R<=1;R++)                  //生成所有安全的图的顶点
		for(H=0;H<=1;H++)
			for(T=0;T<=1;T++)
			{
				for(C=0;C<=1;C++)
				{
					if(Safety(R,H,T,C))
					{
					   G->DXL[i].R=R;
					   G->DXL[i].H=H;
					   G->DXL[i].T=T;
					   G->DXL[i].C=C;
					   i++;			
					}
				}
				G->DingS=i;                             //为图顶点数目赋值
				for(i=0;i<G->DingS;i++)                 //初始化邻接矩阵
					for(j=0;j<G->DingS;j++)
					{
						if(PassRiver(G,i,j))
						G->Matrix[i][j]=G->Matrix[j][i]=1;  //i与j可转化初始化为1
						else
						G->Matrix[i][j]=G->Matrix[j][i]=0;  //i与j不可转化初始化为0
					}
			}
	 return  G;
}
void Traverse(Tu *G,int u,int v)          //用深度优先遍历搜索从u到v的简单路径函数
{
	 int j,k = 0;
	 flags[u] = 1;                              //标记已访问过的顶点
	 for(j = 0;j < G->DingS;j++)
	 if(G->Matrix[u][j] && !flags[j] && !flags[v])
	 {
		  path[u]=j;                              //存储路径
		  Traverse(G,j,v);                        //递归遍历以后的结点
	 }
}
void Print(Tu *G,int k,int l)               //用文字描述每一步骤的含义函数
{
	 switch(k)                                  //k为顶点向量编号
	 {                                          //不同编号的文字含义
	   case 0:  cout<<"农夫,狐狸,鸡,小米都在左岸!"<<endl;
				break;
	   case 1:  if(l == 6)
				{ 
					cout<<"人带鸡回左岸->";
					break;
				}
				else
				{ 
					cout<<"路径错误!"<<endl;
					break;
				}
	   case 2:  if(l == 5)
				{ 
					cout<<"人空手回左岸->";      
					break;
				}
				else
				{
					cout<<"路径错误!"<<endl;           
					break;
				}
	   case 3:  if(l == 8)
				{ 
					cout<<"人带鸡回左岸->";       
					break;
				}
				else
				{ 
					cout<<"路径错误!"<<endl;           
					break;
				}
	   case 4:  if(l == 7)
				{ 
					cout<<"人空手回左岸->";       
					break;
				}
				else
				{
					cout<<"路径错误!"<<endl;           
					break;
				}
	   case 5:  if(l == 0)
				{
					cout<<"人带鸡到右岸->";       
					break;
				}
				else
				{
					cout<<"路径错误!"<<endl;           
					break;
				}
	   case 6:  if(l == 2)
				{ 
					cout<<"人带小米到右岸->";       
					break;
				}
				else
				{ 
					cout<<"路径错误!"<<endl;           
					break;
				}
	   case 7:  if(!G->DXL[l].H)                //在该路径中小米被带到对岸
				{ 
					cout<<"人带狐狸到右岸->";       
					break;
				}
				if(!G->DXL[l].C)                //在该路径中狐被带到对岸
				{ 
					cout<<"人带小米到右岸->";       
					break;
				}
	   case 8:  if( l == 2)
				{ 
					cout<<"人带狐狸到右岸";       
					break;
				}
				else
				{
					cout<<"路径错误!"<<endl;           
					break;
				}
	   case 9:  if(l == 4)
				{ 
					cout<<"人带鸡到右岸->";   	         
					cout<<"过河完毕!"<<endl<<endl;
					break;
				}
				else
				{
					cout<<"路径错误!"<<endl;    
					break;
				}
	 }
}
void PrintPath(Tu *G,int u,int v)      //用顶点向量描述过河路径函数
{
	 int k = u,l = u;
	 while(k != v)                              
	 {
		  Print(G,k,l);                //用文字表述
		  l = k;                       //用l记录路径中当前步骤的前一步骤
		  k = path[k];
	 }                      
	 Print(G,k,l);                     //用文字表述
	 Init(flags);                      //将标志数组置0,便于查找其他的路径
}
void ReSearch(Tu *G,int v)                //再查找其他路径函数
{
	int i = 0,j;
	while(i < G->DingS)                          
	{
		if(!flags[path[i]])               //在没被访问过的结点中再查找
			i = i;
		for(j=path[i]+1;j<G->DingS;j++)   //查找当前结点的上一次邻接点以后的结点
		{
			if(G->Matrix[i][j]!=0 && !flags[j] && !flags[v])//当前结点的上一次邻接点以后的结点存在时,从此进行深度遍历
			{
				path[i] = j;
				Traverse(G,i,v);
			}
			else
			{
				flags[path[i]] = 1;
				i++;
			}//当前结点的上一次邻接点以后的结点不存在时,从下一结点再查找 
		}
	}
}
int main()                                
{
	int i,j;
	Tu *G;
	G = (Tu *)malloc(sizeof(Tu));                
	G = Create(G);               //生成邻接矩阵
	Init(flags);                 //初始化标志矩阵
	i = Search(G,0,0,0,0);       //查找(0,0,0,0)的位置
	j = Search(G,1,1,1,1);       //查找(1,1,1,1)的位置
	Traverse(G,i,j);             //查找i到j的路径
	if(flags[j])
		PrintPath(G,i,j);        //输出路径                        
	ReSearch(G,j);              //再查找其他路径
	if(flags[j])
		PrintPath(G,i,j);        //输出路径
	system("pause");
	return 0;
}  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值