#include  "iostream.h"
#include "string.h"
//定义一个状态节点
typedef struct //存储各个状态
{
int x,y,s;//修道士人数,野人人数,s=0左岸s=1右岸
}state; typedef struct edge
{
int verNo;//顶点号;
int x_boat,y_boat,di;//船上修道士人数,船上野人人数,方向,di=1向右,di=0向左
struct edge* next;
}edge; typedef struct
{
state st;
edge *e;
}vert; typedef struct
{
vert ver[1000] ;
int vNum;
}adjGraph; typedef struct
{
int pos;//pos为该状态在邻接表的顶点表中的位置
int pre;//pre指的是队中当前元素前驱在qu.dt中的位置
}data;
typedef struct
{
data dt[1000];
int front,rear;
}Queue; //创建顶点表,并记录所有状态的个数adj.vNum
void CreteAllState(adjGraph &adj,int m,int n)
{
for (int c1=0;c1<=1;c1++)
for(int m1=0;m1<=m;m1++)
for (int n1=0;n1<=n&&n1<=m1||m1==0&&n1<=n;n1++)//野人要少于修道士人数或全是野人
{
adj.ver[adj.vNum].st.s=c1;
adj.ver[adj.vNum].st.x=m1;
adj.ver[adj.vNum].st.y=n1;
adj.ver[adj.vNum].e=NULL;
cout<<c1<<'\t'<<m1<<'\t'<<n1<<'\t'<<adj.vNum<<endl;
adj.vNum++;
}
}
//在顶点表中查找状态位置(下标)
int SearchState(adjGraph adj,state st)
{
for (int i=0;i<adj.vNum;i++)
if(st.s==adj.ver[i].st.s && st.x==adj.ver[i].st.x && st.y==adj.ver[i].st.y)
return i;
return -1;
}
int CheckState(adjGraph adj,state st,int m,int n)//判断st状态是否可作为第i状态的后续状态,如果是则返回后续状态的位置,否则返回-1;
{
int pos;state st_OtherSide;
st_OtherSide.s=st.s==1?0:1;
st_OtherSide.x=m-st.x;
st_OtherSide.y=n-st.y;
pos=SearchState(adj,st_OtherSide);
if(pos==-1) return -1;
pos=SearchState(adj,st);
if(pos==-1) return -1;
return pos;
}
//创建边表
void CreateEdges(adjGraph &adj,int m,int n,int c)
{
edge *t;state st;int j,k,vNo;
for(int i=0;i<adj.vNum;i++)
{
if (adj.ver[i].st.x+adj.ver[i].st.y>0)//修道士与野人总数大于0
{
if(adj.ver[i].st.y>0)//假如船上全部为野人
for (j=1;j<=adj.ver[i].st.y&&j<=c;j++)
{
st.s=adj.ver[i].st.s==1?0:1;
st.x=m-adj.ver[i].st.x;
st.y=n-(adj.ver[i].st.y-j);
vNo=CheckState(adj,st,m,n);
if(vNo==-1) continue; //非法状态则跳过
t=new edge;//左岸就往右岸的状态转变
t->verNo=vNo;t->di=st.s;t->x_boat=0;t->y_boat=j;
t->next=adj.ver[i].e;//头插法
adj.ver[i].e=t;
}
if(adj.ver[i].st.x>1)//船上有j个修道士与k个野人
for (j=1;j<=adj.ver[i].st.x&&j<=c;j++)//
for (k=0;k<=c-j&&k<=adj.ver[i].st.y;k++)
{
st.s=adj.ver[i].st.s==1?0:1;
st.x=m-(adj.ver[i].st.x-j);
st.y=n-(adj.ver[i].st.y-k);
vNo=CheckState(adj,st,m,n);
if(vNo==-1) continue;//非法状态则跳过
t=new edge;//右岸就往左岸的状态转变
t->verNo=vNo;t->di=st.s;t->x_boat=j;t->y_boat=k;
t->next=adj.ver[i].e;//头插法
adj.ver[i].e=t;
}
}
}
} void Disp(adjGraph adj)
{
edge *e;
for (int i=0;i<adj.vNum;i++)
{
cout<<i<<'\t';
cout<<adj.ver[i].st.s<<'\t';
cout<<adj.ver[i].st.x<<'\t';
cout<<adj.ver[i].st.y<<'\t'; e=adj.ver[i].e;
cout<<endl;
while (e)
{
cout<<'\t'<<"顶点号"<<'\t'<<"方向"<<'\t'<<"船上修道士"<<'\t'<<"船上野人"<<endl;
cout<<'\t'<<e->verNo<<'\t'<<e->di<<'\t'<<e->x_boat<<'\t'<<e->y_boat<<endl;
e=e->next;
}
cout<<endl;
}
} void PrintPath1(adjGraph &adj,Queue &qu,int i)//由i向前找路
{
if (qu.dt[i].pre!=-1)
PrintPath1(adj,qu,qu.dt[i].pre);
int k=qu.dt[i].pos;
cout<<i<<'\t';
cout<<adj.ver[k].st.s<<'\t';
cout<<adj.ver[k].st.x<<'\t';
cout<<adj.ver[k].st.y<<'\t';
cout<<endl;
}
void PrintPath(adjGraph &adj,Queue &qu,int i)//由i向前找路
{
for (int k=0;k<=i;k++)
{
cout<<k<<'\t';
cout<<qu.dt[k].pos<<'\t';
cout<<qu.dt[k].pre<<'\t';
cout<<endl;
}
} void BreadthSearch(adjGraph adj,int* visit,Queue &qu,int x,int y)
{
int stPos,finPos,tag=1;
qu.front=qu.rear=-1;
state st,fin;
st.s=0;st.x=x;st.y=y;
stPos=CheckState(adj,st,x,y);
if(stPos==-1) cout<<"start position error!"<<endl;
fin.s=1;fin.x=x;fin.y=y;
finPos=SearchState(adj,fin);
qu.rear++;
qu.dt[qu.rear].pos=stPos;//起始位置入队
qu.dt[qu.rear].pre=-1;//pre指的是队中当前元素前驱在qu.dt中的位置
while(qu.rear!=qu.front&&tag)
{
qu.front++;//出队一元素
visit[qu.dt[qu.front].pos]=1;
if (qu.dt[qu.front].pos==finPos)
{
tag=0;
cout<<"find the path!"<<endl;
PrintPath1(adj,qu,qu.front);
//插入打印路径的函数
break;
}
edge *e;
e=adj.ver[qu.dt[qu.front].pos].e;//e points to the first adjacent edge;
while (e)
{
if(visit[e->verNo]==0)
{
qu.dt[++qu.rear].pos=e->verNo;
qu.dt[qu.rear].pre=qu.front;
}
e=e->next;
}
}
if(tag==1)
cout<<"cant find the path!"<<endl; } void main()
{
int m,n,c;//修道士人数,野人人数,船上最多可载人数
adjGraph adj;Queue qu;
adj.vNum=0;
cin>>m>>n>>c;
CreteAllState(adj,m,n);
CreateEdges(adj,m,n,c);
Disp(adj);
int visit[1000];
memset(visit,0,sizeof(visit));//把数组置空
BreadthSearch(adj,visit,qu,m,n); }

去掉调试代码:

#include  "iostream.h"
#include "string.h"
//定义一个状态节点
typedef struct //存储各个状态
{
int x,y,s;//修道士人数,野人人数,s=0左岸s=1右岸
}state; typedef struct edge
{
int verNo;//顶点号;
int x_boat,y_boat,di;//船上修道士人数,船上野人人数,方向,di=1向右,di=0向左
struct edge* next;
}edge; typedef struct
{
state st;
edge *e;
}vert; typedef struct
{
vert ver[1000] ;
int vNum;
}adjGraph; typedef struct
{
int pos;//pos为该状态在邻接表的顶点表中的位置
int pre;//pre指的是队中当前元素前驱在qu.dt中的位置
}data;
typedef struct
{
data dt[1000];
int front,rear;
}Queue; //创建顶点表,并记录所有状态的个数adj.vNum
void CreteAllState(adjGraph &adj,int m,int n)
{
for (int c1=0;c1<=1;c1++)
for(int m1=0;m1<=m;m1++)
for (int n1=0;n1<=n&&n1<=m1||m1==0&&n1<=n;n1++)//野人要少于修道士人数或全是野人
{
adj.ver[adj.vNum].st.s=c1;
adj.ver[adj.vNum].st.x=m1;
adj.ver[adj.vNum].st.y=n1;
adj.ver[adj.vNum].e=NULL;
cout<<c1<<'\t'<<m1<<'\t'<<n1<<'\t'<<adj.vNum<<endl;
adj.vNum++;
}
}
//在顶点表中查找状态位置(下标)
int SearchState(adjGraph adj,state st)
{
for (int i=0;i<adj.vNum;i++)
if(st.s==adj.ver[i].st.s && st.x==adj.ver[i].st.x && st.y==adj.ver[i].st.y)
return i;
return -1;
}
int CheckState(adjGraph adj,state st,int m,int n)//判断st状态是否可作为第i状态的后续状态,如果是则返回后续状态的位置,否则返回-1;
{
int pos;state st_OtherSide;
st_OtherSide.s=st.s==1?0:1;
st_OtherSide.x=m-st.x;
st_OtherSide.y=n-st.y;
pos=SearchState(adj,st_OtherSide);
if(pos==-1) return -1;
pos=SearchState(adj,st);
if(pos==-1) return -1;
return pos;
}
//创建边表
void CreateEdges(adjGraph &adj,int m,int n,int c)
{
edge *t;state st;int j,k,vNo;
for(int i=0;i<adj.vNum;i++)
{
if (adj.ver[i].st.x+adj.ver[i].st.y>0)//修道士与野人总数大于0
{
if(adj.ver[i].st.y>0)//假如船上全部为野人
for (j=1;j<=adj.ver[i].st.y&&j<=c;j++)
{
st.s=adj.ver[i].st.s==1?0:1;
st.x=m-adj.ver[i].st.x;
st.y=n-(adj.ver[i].st.y-j);
vNo=CheckState(adj,st,m,n);
if(vNo==-1) continue; //非法状态则跳过
t=new edge;//左岸就往右岸的状态转变
t->verNo=vNo;t->di=st.s;t->x_boat=0;t->y_boat=j;
t->next=adj.ver[i].e;//头插法
adj.ver[i].e=t;
}
if(adj.ver[i].st.x>1)//船上有j个修道士与k个野人
for (j=1;j<=adj.ver[i].st.x&&j<=c;j++)//
for (k=0;k<=c-j&&k<=adj.ver[i].st.y;k++)
{
st.s=adj.ver[i].st.s==1?0:1;
st.x=m-(adj.ver[i].st.x-j);
st.y=n-(adj.ver[i].st.y-k);
vNo=CheckState(adj,st,m,n);
if(vNo==-1) continue;//非法状态则跳过
t=new edge;//右岸就往左岸的状态转变
t->verNo=vNo;t->di=st.s;t->x_boat=j;t->y_boat=k;
t->next=adj.ver[i].e;//头插法
adj.ver[i].e=t;
}
}
}
} void PrintPath1(adjGraph &adj,Queue &qu,int i)//由i向前找路
{
if (qu.dt[i].pre!=-1)
PrintPath1(adj,qu,qu.dt[i].pre);
int k=qu.dt[i].pos;
cout<<i<<'\t';
cout<<adj.ver[k].st.s<<'\t';
cout<<adj.ver[k].st.x<<'\t';
cout<<adj.ver[k].st.y<<'\t';
cout<<endl;
} void BreadthSearch(adjGraph adj,int* visit,Queue &qu,int x,int y)
{
int stPos,finPos,tag=1;
qu.front=qu.rear=-1;
state st,fin;
st.s=0;st.x=x;st.y=y;
stPos=CheckState(adj,st,x,y);
if(stPos==-1) cout<<"start position error!"<<endl;
fin.s=1;fin.x=x;fin.y=y;
finPos=SearchState(adj,fin);
qu.rear++;
qu.dt[qu.rear].pos=stPos;//起始位置入队
qu.dt[qu.rear].pre=-1;//pre指的是队中当前元素前驱在qu.dt中的位置
while(qu.rear!=qu.front&&tag)
{
qu.front++;//出队一元素
visit[qu.dt[qu.front].pos]=1;
if (qu.dt[qu.front].pos==finPos)
{
tag=0;
cout<<"find the path!"<<endl;
PrintPath1(adj,qu,qu.front);
//插入打印路径的函数
break;
}
edge *e;
e=adj.ver[qu.dt[qu.front].pos].e;//e points to the first adjacent edge;
while (e)
{
if(visit[e->verNo]==0)
{
qu.dt[++qu.rear].pos=e->verNo;
qu.dt[qu.rear].pre=qu.front;
}
e=e->next;
}
}
if(tag==1)
cout<<"cant find the path!"<<endl; } void main()
{
int m,n,c;//修道士人数,野人人数,船上最多可载人数
adjGraph adj;Queue qu;
adj.vNum=0;
cin>>m>>n>>c;
CreteAllState(adj,m,n);
CreateEdges(adj,m,n,c);
Disp(adj);
int visit[1000];
memset(visit,0,sizeof(visit));//把数组置空
BreadthSearch(adj,visit,qu,m,n); }

  

最新文章

  1. CSS 伪类 (Pseudo-classes)
  2. MVC5 + EF6 + Bootstrap3 (13) 查看详情、编辑数据、删除数据
  3. barrier()函数
  4. Javascript 笔记与总结(2-15)结构、样式、行为分离
  5. Hibernate,get()和load()区别
  6. AutoBackupForApps
  7. Android基础知识巩固:关于PendingIntent和广播
  8. JavaScript的DOM编程--03--读写属性节点
  9. 一行js代码识别Selenium+Webdriver及其应对方案
  10. 《代码不朽:编写可维护软件的10大要则(C#版)》读后感
  11. 记录js new Date日期处理的一个坑
  12. UI自动化(十一)selenium框架
  13. Spring AOP获取拦截方法的参数名称跟参数值
  14. 学习Shell(二)变量
  15. MAC 无脑编译OpenCV
  16. 手机端用swiper组件 轮播图设置后右侧出现空白 及 部分手机浏览器打开网页空白
  17. guide dpdk
  18. 《Spring实战》第4章--面向切面的Spring--处理通知中的参数(经验总结)
  19. c语言静态断言
  20. 再论C++引用(reference)类型

热门文章

  1. C# 给Word每一页设置不同图片水印
  2. 使用讯飞tts+ffmpeg自动生成视频
  3. c++基础的记录(随笔记录一些基础的东西)
  4. oracle11g在windows下安装
  5. 好久没写作业了,因为组里分配了任务,学习了Resnet和DenseNet,把概要po上来和大家分享。
  6. 金融行业BI可视化报表,直观体验数据的价值
  7. 【C#】通过一个案例 彻底了解 Volatile和 内存屏障
  8. Hadoop - HDFS学习笔记(详细)
  9. 论文解读(GIN)《How Powerful are Graph Neural Networks》
  10. Qt:QList、QStringList