修道士与野人问题(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 ...
随机推荐
- 暑假撸系统7- 熊孩子的捣乱!javascript保存前台状态!
系统大体框架已经搭的差不多了, 往下就是技术性的美化以及修补了,但这也是最最耗费时间的.在这个过程就发现了一个有意思的需求,这里把思路以及解决方案总结下. 因为做的是考试系统,不管是大或者小的考试,本 ...
- ASP.NET Core 6框架揭秘实例演示[06]:依赖注入框架设计细节
由于依赖注入具有举足轻重的作用,所以<ASP.NET Core 6框架揭秘>的绝大部分章节都会涉及这一主题.本书第3章对.NET原生的依赖注入框架的设计和实现进行了系统的介绍,其中设计一些 ...
- 为什么使用Mybatis对JDBC进行包装探究
一.原生JDBC在实际生产中使用存在的影响性能的问题 首先分析使用JDBC的代码: Connection connection = null; PreparedStatement preparedSt ...
- 轻松理解JS中的面向对象,顺便搞懂prototype和__proto__的原理介绍
这篇文章主要讲一下JS中面向对象以及 __proto__,ptototype和construcator,这几个概念都是相关的,所以一起讲了. 在讲这个之前我们先来说说类,了解面向对象的朋友应该都知道, ...
- pytest--conftest.py用法(单独存放fixtrue配置的一个文件)
1.conftest.py文件是什么 单独存放fixtrue配置的一个文件 用处是可以多个不同的pytest测试脚本共用一套fixture配置,代码维护方便 2.conftest.py使用注意事项 c ...
- 使用 matplotlib 显示彩色图像
详细说明见代码注释 """ 介绍如何使用 matplotlib 输入.输出 彩色图像,并简要介绍如何将数组表示形式的图像数据显示为图像 """ ...
- 创新引领,再获嘉誉!Smartbi亮相亚太银行数博会,共话未来银行数字化趋势
4月21日,以"加速数字化,引领银行业务创新"为主题的第六届亚太银行数字化创新博览会在上海盛大开幕.本次高峰论坛吸引了400多位来自学术界.咨询行业以及银行业等不同领域的行业大咖齐 ...
- 【C#基础概念】Ineterface 接口的设计原则
接口设计方式 自顶向下 (如图所示),自底向上(发现类需要结构了就声明一个接口). 接口的作用 用来解耦.继承 接口的本质
- 【C#程序集】为何.NET Core控制台项目发布后是一个dll文件,而不是exe文件?
因为 .NET Core 的控制台应用默认是生成 dll 文件,而没有对应的 exe 文件.如下图所示,是在VS中编译后生成的结果 图中看到的TestVisualizer.exe 只是一个快捷方式, ...
- html页面引用script出现中文乱码问题
在html的head标签中加入代码: <meta http-equiv="Content-Type" content="text/javascript; chars ...