#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. CentOS7防火墙firewall

    一.Firewall 1. 从CentOS7开始,默认使用firewall来配置防火墙,没有安装iptables(旧版默认安装). 2. firewall的配置文件是以xml的格式,存储在 /usr/ ...

  2. k8s初面考点ReplicaSet副本集极限9连击你懂了吗?

    k8s初面考点ReplicaSet副本集极限9连击你懂了吗? k8s考点灵魂拷问9连击 考点之简单描述一下k8s副本集ReplicaSet有什么作用? 考点之为什么ReplicaSet将取代Repli ...

  3. C#CancellationToken/CancellationTokenSource-取消令牌/取消令牌源 CT/CTS

    详细情况:https://www.cnblogs.com/wucy/p/15128365.html 背景 为什么引入取消令牌? Thread.abort()方法会破坏同步锁中代码的原子逻辑,破坏锁的作 ...

  4. 【基础知识】CPU原理之减法、乘法和除法

    中介绍了布尔逻辑.数学和电路的关系,我们也得到了与门.或门.非门.或非门.与非门.异或门等门电路以及一个加法器,并且了解了计算机是如何做加法的,这篇文章介绍一下计算机是如何做减法以及乘除法的. 0x0 ...

  5. 【基础知识】CPU指令周期

    完整执行一条指令所需要的时间 基本概念 指令周期,读取-执行周期(fetch-and-execute cycle)是指CPU要执行指令经过的步骤. 计算机之所以能自动地工作,是因为CPU能从存放程序的 ...

  6. C#析构函数(方法)

    析构方法是在垃圾回收.释放资源时使用的.析构函数用于析构类的实例.备注:    不能在结构中定义析构函数.只能对类使用析构函数.    一个类只能有一个析构函数.    无法继承或重载析构函数.    ...

  7. 服务器CPU很高-怎么办(Windbg使用坑点)

    最近,碰到了一个线上CPU服务器很高的问题,并且也相当紧急,接到这个任务后,我便想到C#性能分析利器,Windbg. 终于在折腾半天之后,找出了问题,成功解决,这里就和大家分享一下碰到的问题. 问题1 ...

  8. Shell脚本编写登陆小程序.sh

    转至:https://www.cnblogs.com/gaohongyu/articles/12072594.html #!/bin/bash #Author:GaoHongYu #QQ:106176 ...

  9. Python:读取Excel 不带第一行标题

    #根据第0到第1列进行重建 0-X 1-Y PX=sheet_name.col_values(0)[1:] PY=sheet_name.col_values(1)[1:] 读取的某一列后在后边加[1: ...

  10. (第二章第一部分)TensorFlow框架之文件读取流程

    本章概述:在第一章的系列文章中介绍了tf框架的基本用法,从本章开始,介绍与tf框架相关的数据读取和写入的方法,并会在最后,用基础的神经网络,实现经典的Mnist手写数字识别. 有四种获取数据到Tens ...