JAVA野人_Java实现传教士与野人过河问题
1 问题定义
河的两岸有三个传教士和三个野人需要过河,目前只有一条能装下两个人的船,在河的任何一方或者船上,如果野人的人数大于传教士的人数,那么传教士就会被野人攻击,怎么找出一种安全的渡河方案呢?
2 算法分析
首先,先来看看问题的初始状态和目标状态,定义河的两岸分别为左岸和右岸,设定状态集合为(左岸传教士人数,右岸野人数,右岸传教士人数,右岸野人数,船的位置),船的位置:-1表示船在左岸,1表示船在右岸。
初始状态:(3,3,0,0,0,-1)
目标状态:(0,0,3,3,1)
然后,整个问题就抽象成了怎样从初始状态经中间的一系列状态达到目标状态。问题状态的改变是通过划船渡河来引发的,所以合理的渡河操作就成了通常所说的算符,根据题目要求,可以得出以下5个算符(按照渡船方向的不同,也可以理解为10个算符):
渡1野人、渡1传教士、渡1野人1传教士、渡2野人、渡2传教士
根据船的位置,向左移或向右移通过递归依次执行5种算符,判断是否找到所求,并排除不符合实际的状态,就可以找到所有可能的解,如图1所示为递归函数流程图。
3 源代码
package joepa.javaweb;
import java.util.ArrayList;
import java.util.List;
public class River {
public static void main(String[] args) {
List lastParameters = new ArrayList();
List operation = new ArrayList();
RiverSides currentState = new RiverSides(3, 3, 0, 0, 1);
lastParameters.add(currentState);
cvsWdfs(currentState, lastParameters, operation, 0);
lastParameters.remove(lastParameters.size() – 1);
System.out.println(“执行完毕”);
}
private static int mycount = 0;// 统计成功过河次数
public static int cvsWdfs(RiverSides lastState,
List lastParameters, List operation,
int ifboacurrentStatety) {
if (lastState.getChurchR() == 3 && lastState.getWildR() == 3) {
mycount++;
System.out.println(“第” + mycount + “次成功过河”);
System.out.println(“传教士 野人 | 移动方向”);
for (int i = 0; i < operation.size(); i++) {
System.out.println(operation.get(i));
}
return 0;
}
// 判断过河操作否重复,去除死循环
for (int i = 0; i < lastParameters.size() – 1; i++) {
if (lastParameters.get(i).getWildL() == lastState.getWildL()
&& lastParameters.get(i).getChurchL() == lastState
.getChurchL()) {
if (lastState.getBoat() == lastParameters.get(i).getBoat())
return 0;
}
}
// 检验人数数据合法性
if (lastState.getChurchL() < 0 || lastState.getWildL() < 0
|| lastState.getChurchR() < 0 || lastState.getWildR() < 0)
return 0;
// 传教士是否被吃
if ((lastState.getChurchL() < lastState.getWildL() && lastState .getChurchL() != 0)
|| (lastState.getChurchR() < lastState.getWildR() && lastState.getChurchR() != 0))
return 0;
// 递归执行五类过河操作,boat=-1船在左岸,boat=1船在右岸,传入boat为上一次船位置
// 下次应当取反
RiverSides currentState = new RiverSides();
// 两个传教士过河
if (lastState.getBoat() == 1)
operation.add(” 2 0 | 左岸->右岸”);
else
operation.add(” 2 0 | 右岸->左岸”);
currentState.setChurchL(lastState.getChurchL() – 2
* lastState.getBoat());
currentState.setWildL(lastState.getWildL());
currentState.setChurchR(lastState.getChurchR() + 2
* lastState.getBoat());
currentState.setWildR(lastState.getWildR());
currentState.setBoat(-lastState.getBoat());
lastParameters.add(currentState);
cvsWdfs(currentState, lastParameters, operation, 0);
operation.remove(operation.size() – 1);
lastParameters.remove(lastParameters.size() – 1);
// 两个野人过河
if (lastState.getBoat() == 1)
operation.add(” 0 2 | 左岸->右岸”);
else
operation.add(” 0 2 | 右岸->左岸”);
currentState.setChurchL(lastState.getChurchL());
currentState.setWildL(lastState.getWildL() – 2 * lastState.getBoat());
currentState.setChurchR(lastState.getChurchR());
currentState.setWildR(lastState.getWildR() + 2 * lastState.getBoat());
currentState.setBoat(-lastState.getBoat());
lastParameters.add(currentState);
cvsWdfs(currentState, lastParameters, operation, 0);
operation.remove(operation.size() – 1);
lastParameters.remove(lastParameters.size() – 1);
// 一个野人,一个传教士
if (lastState.getBoat() == 1)
operation.add(” 1 1 | 左岸->右岸”);
else
operation.add(” 1 1 | 右岸->左岸”);
currentState.setChurchL(lastState.getChurchL() – 1
* lastState.getBoat());
currentState.setWildL(lastState.getWildL() – 1 * lastState.getBoat());
currentState.setChurchR(lastState.getChurchR() + 1
* lastState.getBoat());
currentState.setWildR(lastState.getWildR() + 1 * lastState.getBoat());
currentState.setBoat(-lastState.getBoat());
lastParameters.add(currentState);
cvsWdfs(currentState, lastParameters, operation, 0);
operation.remove(operation.size() – 1);
lastParameters.remove(lastParameters.size() – 1);
// 一个传教士过河
if (lastState.getBoat() == 1)
operation.add(” 1 0 | 左岸->右岸”);
else
operation.add(” 1 0 | 右岸->左岸”);
currentState.setChurchL(lastState.getChurchL() – 1
* lastState.getBoat());
currentState.setWildL(lastState.getWildL());
currentState.setChurchR(lastState.getChurchR() + 1
* lastState.getBoat());
currentState.setWildR(lastState.getWildR());
currentState.setBoat(-lastState.getBoat());
lastParameters.add(currentState);
cvsWdfs(currentState, lastParameters, operation, 0);
operation.remove(operation.size() – 1);
lastParameters.remove(lastParameters.size() – 1);
// 一个野人过河
if (lastState.getBoat() == 1)
operation.add(” 0 1 | 左岸->右岸”);
else
operation.add(” 0 1 | 右岸->左岸”);
currentState.setChurchL(lastState.getChurchL());
currentState.setWildL(lastState.getWildL() – 1 * lastState.getBoat());
currentState.setChurchR(lastState.getChurchR());
currentState.setWildR(lastState.getWildR() + 1 * lastState.getBoat());
currentState.setBoat(-lastState.getBoat());
lastParameters.add(currentState);
cvsWdfs(currentState, lastParameters, operation, 0);
operation.remove(operation.size() – 1);
lastParameters.remove(lastParameters.size() – 1);
return 0;
}
}
//定义过河状态类
class RiverSides {
private int churchL;
private int wildL;
private int churchR;
private int wildR;
private int boat;
public RiverSides() {
}
public int getChurchL() {
return churchL;
}
public void setChurchL(int churchL) {
this.churchL = churchL;
}
public int getWildL() {
return wildL;
}
public void setWildL(int wildL) {
this.wildL = wildL;
}
public int getChurchR() {
return churchR;
}
public void setChurchR(int churchR) {
this.churchR = churchR;
}
public int getWildR() {
return wildR;
}
public void setWildR(int wildR) {
this.wildR = wildR;
}
public int getBoat() {
return boat;
}
public void setBoat(int boat) {
this.boat = boat;
}
public RiverSides(int churchL, int wildL, int churchR, int wildR, int boat) {
super();
this.churchL = churchL;
this.wildL = wildL;
this.churchR = churchR;
this.wildR = wildR;
this.boat = boat;
}
}
JAVA野人_Java实现传教士与野人过河问题相关推荐
- 野人与传教士过河java_传教士和野人过河(经典MC问题)
这个问题本来是<人工智能技术导论>第三章的课后题,今天上午考试正巧考到了这道题,要我们画状态转换图,我之前思考过一点,所以写出的状态表示应该没有问题,但这些状态太多了.......,十来种 ...
- 传教士与野人过河问题 人工智能实验算法
问题描述 有 N 个传教士和 N 个野人来到河边渡河,河岸有一条船,每次至多可供 k 人乘渡.问:传教士为了安全起见,应如何规划摆渡方案,使得任何时刻, 河两岸以及船上的野人数目总是不超过传教士的数目 ...
- 传教士与野人过河问题(A*搜索 C++)
传教士与野人过河问题: 任意时刻,左岸.右岸.船上如果传教士人数少于野人人数,传教士就会被野人吃掉.当然野人会划船.传教士人数为0也是可以的. 启发函数 f=g+h. g当前结点所在解空间树的深度. ...
- C语言版,传教士与野人渡河问题,使用深度优先搜索法求解(DFS),变态版,随便输入人数和船的最大载人数,人工智能经典题目,简单易懂,注释到位,没有bug
目录 一.问题描述 二.迟来的代码 运行截图 三.简单分析 一.问题描述 有n个传教士和n个野人准备渡河,但只有一条能容纳c个人的小船,为了防止野人侵犯传教士,要求无论在何处,传教士的人数不得少于野人 ...
- 人工智能实验二——prolog语言求解渡河问题(传教士和野人渡河,农夫渡河问题)实现详解
农夫渡河问题求解 这两个问题都是渡河问题,思路和方式是一样的:给出求解Prolog代码: 问题描述 一个农夫带着一匹狼.一只羊.一颗白菜要过河, 只有一条船而且 农夫每次最多只能带一个动物或物品过河, ...
- 【C++】人工智能实验一 猴子摘香蕉/传教士与野人(含完整代码与状态迁移图)
文章目录 一.猴子摘香蕉问题 1.问题描述 2.解题思路 3.实验结果及分析 实验结果一 实验结果二 实验结果三 4.实验结果 5.实验代码 二.传教士(牧师)与野人问题 1.问题描述 2.实验步骤 ...
- python深度优先搜索传教士和野人_传教士和野人问题解题思路
传教士和野人渡河问题 刘宪国050422023 野人过河问题描述如下:有三个传教士和三个野人过河,只有一条能装下两个人的船,在河的任何一方或者船上,如果野人的人数大于传教士的人数,那么传教士就会有危险 ...
- AI传教士和野人渡河问题-实验报告
一 题目要求: 设有m个传教士和n个野人来到河边,打算乘一只船从左岸渡到右岸去,该船每次最多载3人.在任何时候,如果野人人数超过传教士人数,那么野人就会把传教士吃掉.他们怎样才能用这条船安全地把所有人 ...
- 【算法】传教士和野人问题
有N个传教士和N个野人来到河边准备渡河,河岸有一条船,每次至多可供k人乘渡.问传教士为了安全起见,应如何规划摆渡方案,使得任何时刻,在河的两岸以及船上的野人数目总是不超过传教士的数目.即求解传教士和野 ...
最新文章
- 删除数据为0所在的行
- 一个感染型的病毒逆向分析
- Android RecyclerView和ScrollView嵌套使用
- SAP C4C的扩展字段添加到UI之后,还需要额外的步骤,才能将其添加到OData里
- Android 获取当前的时间。年月日,时分秒,星期几
- 【BZOJ 3339 / BZOJ 3585 / luogu 4137】Rmq Problem / mex
- 谈谈C#中的三个关键词new , virtual , override
- C#—Dev XtraTabControl操作总结如动态增加Tab和关闭选项卡方法等
- MyEclipse提示Errors occurred during the build
- 【Python笔记】列表的用法
- ATmega128单片机](熔丝修改后无法烧录程序情况)
- 北斗时间周和GPS时间周计算,JAVA为例
- haswell架构_一个月拥有Intel Haswell原型
- 值得收藏的JavaScript代码
- 天涯上令人肝肠寸断的100个签名
- markdown神器 -Typora使用教程笔记
- batchsize和数据量设置比例_1. 项目涉及技术
- 什么是SQL注入式攻击 如何防范
- python的mysql数据查询及报错AttributeError: 'Connection' object has no attribute 'curson'
- JS事件处理这一篇就够了!!
热门文章
- i3处理器_为什么Intel的处理器很保值?新款i3吊打老款i5而其价格依旧虚高
- 计算机网络/谢希仁(第八版)第二章习题
- python为什么冷门_python 冷门 知识
- 计算机术语写祝福语,祝福词语大全
- 他们是你学生时期的噩梦,但现在你可以把他们按在墙上摩擦了……
- Python操作Excel造成的科学记数法问题
- Bootstrap4官方文档 | v4核心 -- 组件(一)
- 不会俄语的他闯荡世界杯:科大讯飞这样铸造秘密武器
- 交易所、证券知多少?浅析(一)
- 计算机屏幕抖动怎么办,小编教你电脑屏幕闪烁与屏幕抖动怎么办