修道士与野人问题(BFS广度搜索)
#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广度搜索)的更多相关文章
- 记录----第一次使用BFS(广度搜索)学习经验总结
学习经验记录与分享—— 最近在学习中接触到了一种解决最短路径的实用方法----BFS(广度搜索),在这里总结并分享一下第一次学习的经验. 首先第一个要了解的是"queue"(队列函 ...
- 八数码问题:C++广度搜索实现
毕竟新手上路23333,有谬误还请指正. 课程设计遇到八数码问题(这也是一坨),也查过一些资料并不喜欢用类函数写感觉这样规模小些的问题没有必要,一开始用深度搜索却发现深搜会陷入无底洞,如果设定了深度限 ...
- BFS广度优先搜索 poj1915
Knight Moves Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 25909 Accepted: 12244 Descri ...
- 0算法基础学算法 搜索篇第二讲 BFS广度优先搜索的思想
dfs前置知识: 递归链接:0基础算法基础学算法 第六弹 递归 - 球君 - 博客园 (cnblogs.com) dfs深度优先搜索:0基础学算法 搜索篇第一讲 深度优先搜索 - 球君 - 博客园 ( ...
- 图的遍历BFS广度优先搜索
图的遍历BFS广度优先搜索 1. 简介 BFS(Breadth First Search,广度优先搜索,又名宽度优先搜索),与深度优先算法在一个结点"死磕到底"的思维不同,广度优先 ...
- Leetcode 课程表 C++ 图的深度搜索和广度搜索练习
广度搜索(degree) struct GraphNode{ int label; vector<GraphNode*> neighbours; GraphNode(int x):labe ...
- 算法竞赛——BFS广度优先搜索
BFS 广度优先搜索:一层一层的搜索(类似于树的层次遍历) BFS基本框架 基本步骤: 初始状态(起点)加到队列里 while(队列不为空) 队头弹出 扩展队头元素(邻接节点入队) 最后队为空,结束 ...
- 深度优先dfs与广度bfs优先搜索总结+例题
DFS(Deep First Search)深度优先搜索 深度优先遍历(dfs)是对一个连通图进行遍历的算法.它的思想是从一个顶点开始,沿着一条路一直走到底,如果发现不能到达目标解,那就返回到上一个节 ...
- 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 ...
随机推荐
- Vue 源码解读(2)—— Vue 初始化过程
当学习成为了习惯,知识也就变成了常识. 感谢各位的 点赞.收藏和评论. 新视频和文章会第一时间在微信公众号发送,欢迎关注:李永宁lyn 文章已收录到 github 仓库 liyongning/blog ...
- JwtAccessTokenConverter问题整理
Cannot convert access token to JSON 授权服务颁发token(未进行公私钥加密)后,携带此token请求资源服务,提示此错误. 使用token可以在线解析,跟踪代码后 ...
- DotNet Dictionary 实现简介
一:前言 本来笔者对DotNet的Hashtable及Dictionary认识一直集中在使用上,一个直接用object 一个可以用泛型,以前也只大概看过Hashtable的实现.最近查MSDN时发现有 ...
- MybatisPlus字段自动填充配置
实体类 @ApiModelProperty(value = "创建时间") @TableField(fill = FieldFill.INSERT) private Date gm ...
- python中try...excpet多种使用方法
1 print('\n欢迎使用除法计算器!\n') 2 3 while True: 4 try: 5 x = input('请你输入被除数:') 6 y = input('请你输入除数:') 7 z ...
- 渗透测试之本地文件包含(LFI)
一.本地文件包含 本地文件包含漏洞指的是包含本地的php文件,而通过PHP文件包含漏洞入侵网站,可以浏览同服务器所有文件,并获得webshell. 看见?page=标志性注入点,提示我们输入?=pag ...
- 【转】VMWare中的Host-only、NAT、Bridge
背景:A是本机,A1,A2是虚拟机,B是外部联网的机器 host-only(主机模式): A可以和A1,A2互通,A1,A2 -> B不可以,B -> A1,A2不行 bridge(桥接模 ...
- 使用Helm安装harbor
使用nfs共享存储搭建的pvc(此次都放在一个vpc下): harbor使用nodePort方式部署,不使用ssl: 准备工作: 准备好harbor用的pvc: 安装好helm,添加好可用源: 因为使 ...
- 使用Oracle的PROFILE对用户资源限制和密码限制
转至:https://blog.csdn.net/zhuomingwang/article/details/6444240?utm_medium=distribute.pc_relevant.none ...
- (第一章第五部分)TensorFlow框架之变量OP
系列博客链接: (一)TensorFlow框架介绍:https://www.cnblogs.com/kongweisi/p/11038395.html (二)TensorFlow框架之图与Tensor ...