#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); }

  

修道士与野人问题(BFS广度搜索)的更多相关文章

  1. 记录----第一次使用BFS(广度搜索)学习经验总结

    学习经验记录与分享—— 最近在学习中接触到了一种解决最短路径的实用方法----BFS(广度搜索),在这里总结并分享一下第一次学习的经验. 首先第一个要了解的是"queue"(队列函 ...

  2. 八数码问题:C++广度搜索实现

    毕竟新手上路23333,有谬误还请指正. 课程设计遇到八数码问题(这也是一坨),也查过一些资料并不喜欢用类函数写感觉这样规模小些的问题没有必要,一开始用深度搜索却发现深搜会陷入无底洞,如果设定了深度限 ...

  3. BFS广度优先搜索 poj1915

    Knight Moves Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 25909 Accepted: 12244 Descri ...

  4. 0算法基础学算法 搜索篇第二讲 BFS广度优先搜索的思想

    dfs前置知识: 递归链接:0基础算法基础学算法 第六弹 递归 - 球君 - 博客园 (cnblogs.com) dfs深度优先搜索:0基础学算法 搜索篇第一讲 深度优先搜索 - 球君 - 博客园 ( ...

  5. 图的遍历BFS广度优先搜索

    图的遍历BFS广度优先搜索 1. 简介 BFS(Breadth First Search,广度优先搜索,又名宽度优先搜索),与深度优先算法在一个结点"死磕到底"的思维不同,广度优先 ...

  6. Leetcode 课程表 C++ 图的深度搜索和广度搜索练习

    广度搜索(degree) struct GraphNode{ int label; vector<GraphNode*> neighbours; GraphNode(int x):labe ...

  7. 算法竞赛——BFS广度优先搜索

    BFS 广度优先搜索:一层一层的搜索(类似于树的层次遍历) BFS基本框架 基本步骤: 初始状态(起点)加到队列里 while(队列不为空) 队头弹出 扩展队头元素(邻接节点入队) 最后队为空,结束 ...

  8. 深度优先dfs与广度bfs优先搜索总结+例题

    DFS(Deep First Search)深度优先搜索 深度优先遍历(dfs)是对一个连通图进行遍历的算法.它的思想是从一个顶点开始,沿着一条路一直走到底,如果发现不能到达目标解,那就返回到上一个节 ...

  9. poj3984 广度搜索BFS

      迷宫问题 Description 定义一个二维数组: int maze[5][5] = { 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1 ...

随机推荐

  1. MyBatis功能点二:从责任链设计模式的角度理解插件实现技术

    MyBatis允许对其四大组件(Executor,StatementHandler,ParameterHandler, ResultSetHandler)进行增强处理.在创建四大组件对象的时候 1.每 ...

  2. Paxos 学习笔记2 - Multi-Paxos

    Paxos 学习笔记2 - Multi-Paxos 图片来自 John Ousterhout 的 Raft user study 系列课程 Multi-Paxos 论文里对很多问题并没有描述清楚,所以 ...

  3. 微信小程序wifi控制开发

    小程序wifi控制开发方案 ----- 由小程序通过公众号给wifi控制板进行配网,后台服务器自动生成设备名并注册在数据库中,wifi控制板自动保存生成的设备名,小程序可读取WIFI控制板的数据,控制 ...

  4. NTLK情感分析安装与使用的两种方式 nltk-python

    下载安装到实战详细步骤 NLTK下载安装 先使用pip install nltk 安装包 然后运行下面两行代码会弹出如图得GUI界面,注意下载位置,然后点击下载全部下载了大概3.5G. import ...

  5. C#10 新功能

    C# 10.0 向 C# 语言添加了以下功能和增强功能: 记录结构 结构类型的改进 可使用 const 内插字符串 内插字符串处理程序 global using 指令 文件范围的命名空间声明 扩展属性 ...

  6. c语言结构体中的一个char数组怎么赋值?

    目录 前景提示 这里的结构体处理的步骤 一.char数组类型的处理 二.char数组指针类型的处理 三.全部代码 1. char数组 2. char数组指针 结语 前景提示 定义一个结构体,结构体中有 ...

  7. spark submit local遇到路径hdfs的问题

    有时候第一次执行 spark submit --master local[*] 单机模式的时候,可以对linux本地路径进行输出.但是有时候提交到yarn的时候,是自动加上hdfs的路径这没问题, 但 ...

  8. c/c++ 常见字符串处理函数总结 strlen/sizeof strcpy/memcpy/strncpy strcat/strncat strcmp/strncmp sprintf/sscanf strtok/split/getline atoi/atof/atol

    这里总结工作中经常用到的一些c/c++的字符串处理方法,标黑的是使用频率较高的   1.strlen函数:计算目标字符串长度,    格式:strlen(字符指针指向区域) 注意1:①不包含字符串结束 ...

  9. JZ-004-重建二叉树

    重建二叉树 题目描述 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树.假设输入的前序遍历和中序遍历的结果中都不含重复的数字.例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序 ...

  10. 推动式&拉动式生产

    拉动式:订单发给最后一个单元 推动式:订单发给第一个单元