#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;
}
农夫过河
最新推荐文章于 2015-10-11 12:05:29 发布