商人过河问题(二)java实现
本文实现的java版商人过河是参考http://wenku.baidu.com/link?url=dpe2AC8mCjpGnclFv6iZy88_vqYm3bED4QDpSkAI4ssgs7BhntuuJTlw6_R1N02efR7CfQB8swuCDpROC3GoAqxcPNMTv7l5d1AHamcwCne实现,有兴趣的可以看原文。
反正我是没跑通。。。自己调了很久。。。。不多说,直接贴代码。运行不通过找我。。。
通用版实现。
package mechants_River;
/**
* m 商人人数
* s 随从 人数
* dual 对象表示商人和随从的组成状态,也就是一次渡河方案。
* add minus 状态变迁的计算
* @author tina
*
*/
public class Dual {
int m, s; public Dual(int m, int s) {
this.m = m;
this.s = s;
} Dual add(Dual e) {
return new Dual(this.m + e.m, this.s + e.s);
} Dual minus(Dual e) {
return new Dual(this.m - e.m, this.s - e.s);
}
public boolean greaterOrEqual(Dual d){
//System.out.println("is Valid"+this.m+" "+this.s+"----"+d.m+" "+d.s);
return (this.m>=d.m&&this.s>=d.s? true:false);
}
}
package mechants_River; import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet; public class Path {
Dual carryingSchema[]; // 小船可提供的载人方案
Dual initStatus; // 初始状态
Dual endStatus; // 终止状态
List<Node> path = new ArrayList<Node>(); // 过河路径
Set<Node> iNode = new TreeSet(); // 孤立结点 public Path(int merchant, int servant, int carrying) {
initStatus = new Dual(merchant, servant);
endStatus = new Dual(0, 0);
buildCarryingSchema(carrying);
findPath();
if (path.isEmpty()) {
System.out.println("Can't solve the problem");
} else {
for (Node e : path) {
System.out.println(e);
}
}
} public static void main(String[] args) {
Path p = new Path(5, 5, 2);
} public boolean isRepeat() {
return path.contains(this);
} /**
* 构建渡河方案 根据小船的最大可载人数且小船不能空 计算可行方案 每个方案表示一个dual 对象 并把保存在carryingSchema中。
* 在Node中,通过数组下标来引用小船的载人方案。 数组既可以正向遍历,也可以反向遍历,所有的载人方案,按总人数进行降序排列
*
* @param carrying
*/
public void buildCarryingSchema(int carrying) {
int size = (2 + carrying + 1) * carrying / 2; // 方案总数
carryingSchema = new Dual[size];
// 小船载人方案;按人数降序排列
for (int i = 0, total = carrying; total > 0; total--) {
for (int m = total; m >= 0; m--) {
carryingSchema[i++] = new Dual(m, total - m);
}
}
} /**
* 使用穷举法,搜索一条即初始状态initStatus至终止状态endStatus的迁移路径 step表示渡河步骤,从0开始,step为偶数,表示前行
* 小船前行时,正向遍历表carrySchema
* 如果无法找到可行的方案,则当前结点为孤立结点,则从path中删除,置入孤立结点集合中,同时step回退一步
* ,继续搜索可行的渡河方案。当step<0时,则表示无法找到可行的渡河方案,path将为空。
*/
public void findPath() {
Dual curStatus = initStatus;
int step = 0;
Node node = null, rnode = null;
while (step >= 0) {
int direction = (step % 2 == 0 ? Node.FORWARD : Node.BACKWAED);
int idx;
if (direction == Node.FORWARD) {
idx = 0;
// mode不空,表示发送路径回退。需要跳过该结点已尝试的方案
if (rnode != null) {
idx = rnode.idx + 1;
rnode = null;
}
} else {
// 方向为backword
idx = carryingSchema.length - 1;
// mode不空,表示发送路径回退.需要跳过结点
if (rnode != null) {
idx = rnode.idx - 1;
rnode = null;
}
}
boolean found = false;
while (!found && idx >= 0 && idx < carryingSchema.length) { node = new Node(curStatus, direction, idx);
if (node.isValid() && // 渡河方案是否有效
node.isSecure() && // 状态是否安全
!node.isRepeat() && // 结点不能重复
!node.isIsolated()) // 非孤立结点
{
found = true;
} else {
if (direction == Node.FORWARD)
idx++; // 顺序搜索
else
idx--; // 逆序搜索
}
} if (!found) { // 未找到可行的渡河方案
step--; // 回退一步, 并删除当前结点
if (step >= 0) {
curStatus = path.get(step).status;
rnode = path.remove(step);
iNode.add(rnode); // 孤立结点 }
continue;
} path.add(node); // 把当前结点加入路径中
if (node.isEnd())
break; // 是否到达终止状态
curStatus = node.nextStatus(); // 当前状态变迁 step++;
System.out
.println(step + " " + node.status.m + " " + node.status.s);
}
}
/**
* status 节点方向
* direction 渡河方向
* idx 索引,指向小船的载人方案 carryingSchema[]
* @author tina
* Node 表示整个渡河方案的每个步骤,每个结点由结点状态(商人和随从的人数)、渡河方向和渡河方案组成
*/
public class Node implements Comparable<Node> {
Dual status;
int direction;
int idx;
public static final int FORWARD = 0; // 前进
public static final int BACKWAED = 1; // 返回 public Node(Dual status, int direction, int idx) {
this.status = status;
this.direction = direction;
this.idx = idx;
} @Override
public int compareTo(Node e) {
return this.toString().compareTo(e.toString());
}
@Override
public String toString() {
return "("+this.status.m+","+this.status.s+")" + (direction == FORWARD ? " ---> " : " <--- ")+"("+carryingSchema[this.idx].m+","+carryingSchema[this.idx].s+")";
} public boolean isIsolated() {
// int direction = this.nextDirection();
Dual status = this.nextStatus();
for (Node e : iNode) {
if (direction == e.direction && status.equals(e.status)) {
return true;
}
}
return false;
} Dual nextStatus() {
return direction == FORWARD ? this.status
.minus(carryingSchema[idx]) : this.status
.add(carryingSchema[idx]);
} public boolean equals(Object e) {
if (this == e)
return true;
if (!(e instanceof Node))
return false;
Node o = (Node) e;
return this.status.equals(o.status)
&& this.direction == o.direction && this.idx == o.idx;
} /**
* 当向前渡河时,要求本岸商人和随从人数分别大于等于渡河方案指定的商人和随从人数;
* 当小船返回时,要求对岸商人和随从人数分别大于等于渡河方案指定的商人和随从人数
*
* @return
*/
public boolean isValid() {
return this.direction == FORWARD ? status
.greaterOrEqual(carryingSchema[idx]) : initStatus.minus(
status).greaterOrEqual(carryingSchema[idx]);
}
/**
* 判断结点的状态是否有效,这是实际问题的一具体约束,即要求结点状态中商人人数或者为0,或者不小于随从人数。
* @return
*/
public boolean isSecure() { Dual next = this.nextStatus(); return (next.m == 0 || next.m >= next.s)
&& (initStatus.m - next.m == 0 || initStatus.m - next.m >= initStatus.s
- next.s);
} public boolean isRepeat() {
return iscontains(path);
} public boolean iscontains(List<Node> p) {
for (int i = 0; i < p.size(); i++) {
Node o = p.get(i);
if (this.status.m == o.status.m
&& (this.status.s == o.status.s)
&& this.direction == o.direction && this.idx == o.idx) {
System.out.println("equal");
return true;
}
}
if(p.size()>=1&&this.idx==p.get(p.size()-1).idx){
return true;
}
return false;
} public boolean isEnd() {
Dual next = this.nextStatus();
return next.m==endStatus.m&&next.s==endStatus.s;
}
} }
商人过河问题(二)java实现的更多相关文章
- 实验二 Java面向对象程序设计
实验二 Java面向对象程序设计 实验内容 1. 初步掌握单元测试和TDD 2. 理解并掌握面向对象三要素:封装.继承.多态 3. 初步掌握UML建模 4. 熟悉S.O.L.I.D原则 5. 了解设计 ...
- 20145213《Java程序设计》实验二Java面向对象程序设计实验报告
20145213<Java程序设计>实验二Java面向对象程序设计实验报告 实验内容 初步掌握单元测试和TDD 理解并掌握面向对象三要素:封装,继承,多态 初步掌握UML建模 熟悉S.O. ...
- 20145206《Java程序设计》实验二Java面向对象程序设计实验报告
20145206<Java程序设计>实验二Java面向对象程序设计实验报告 实验内容 初步掌握单元测试和TDD 理解并掌握面向对象三要素:封装.继承.多态 初步掌握UML建模 熟悉S.O. ...
- 20145308刘昊阳 《Java程序设计》实验二 Java面向对象程序设计 实验报告
20145308刘昊阳 <Java程序设计>实验二 Java面向对象程序设计 实验报告 实验名称 Java面向对象程序设计 实验内容 初步掌握单元测试和TDD 理解并掌握面相对象三要素:封 ...
- 20145113 实验二 Java面向对象程序设计
20145113 实验二 Java面向对象程序设计 实验内容 初步掌握单元测试和TDD 理解并掌握面向对象三要素:封装.继承.多态 初步掌握UML建模 熟悉S.O.L.I.D原则 了解设计模式 1.初 ...
- JAVA课程实验报告 实验二 Java面向对象程序设计
北京电子科技学院(BESTI) 实 验 报 告 课程:Java程序设计 班级:1353 姓名:韩玉琪 学号:20135317 成绩: 指导教师:娄嘉 ...
- 20145225唐振远 实验二 "Java面向对象程序设计"
20145225<Java程序设计> 实验二 Java面向对象程序设计 实验报告 实验内容 初步掌握单元测试和TDD 理解并掌握面向对象三要素:封装.继承.多态 初步掌握UML建模 熟悉S ...
- 20145208 实验二 Java面向对象程序设计
20145208 实验二 Java面向对象程序设计 实验内容 初步掌握单元测试和TDD 理解并掌握面向对象三要素:封装.继承.多态 初步掌握UML建模 熟悉S.O.L.I.D原则 了解设计模式 实验步 ...
- 20162311 实验二 Java面向对象程序设计 实验报告
实验二 Java面向对象程序设计 实验内容 1. 初步掌握单元测试和TDD 2. 理解并掌握面向对象三要素:封装.继承.多态 3. 初步掌握UML建模 4. 熟悉S.O.L.I.D原则 5. 了解设计 ...
随机推荐
- 关于oracle动态视图v$datafile和v$datafile_header(转)
v$datafile是从oracle的控制文件中获得的数据文件的信息v$datafile_header是从数据文件的头部在正常运行下,两者的检查点SCN值是一致的,但当datafile出现损坏时可以用 ...
- 类linux系统/proc/sysrq-trigger文件功能作用
立即重启计算机 echo "b" > /proc/sysrq-trigger 立即关闭计算机 echo "o" > /proc/ ...
- Java语言程序设计(基础篇) 第八章 多维数组
第八章 多维数组 8.2 二维数组的基础知识 二维数组中的元素通过行和列的下标来访问. 8.2.1 声明二维数组变量并创建二维数组 下面是二维数组的语法: 数据类型[][] 数组名; int[][] ...
- Python高阶函数
在Python中,函数名也是一个变量,可以进行赋值 高阶函数是至少满足下列一个条件的函数: 接受一个或多个函数作为输入 输出一个函数 函数名也可以作为函数参数,还可以作为函数返回值 def f(n) ...
- [置顶] Android开发实战记录(三)---HelloWorld
1.新建Android项目,选择Android Project,然后Next 2.填写项目名称HelloWorld然后next,这里注意下,Java开发的命名规范 3.选择Android SDK版本, ...
- MVC4 jquery 样式 主题 用法(案例)
MVC4已经自带了jquery,新建的项目,基本上什么都不用添加就可以运行,跑项目.(集成了那么多东西,jquery,modernizr,自带的默认权限,生成的模板,但是缺没有一个统一的文档或者什么去 ...
- struts2 action重定向
struts2的结果类型: <action name="loginAction" class="com.itheima.action.LoginAction&quo ...
- Reflux 使用教程
Reflux是根据React的flux创建的单向数据流类库.Reflux的单向数据流模式主要由actions和stores组成.例如,当组件list新增item时,会调用actions的某个方法(如a ...
- Android studio教程:[6]创建多个Activity
通常来说,一个android应用程序不止一个Activity(活动),更不止一个界面.于是需要创建多个Activity来满足应用程序的要求,这里我将告诉大家如何添加新的Activity,并实现Acti ...
- 2015.4.16-C#中ref和out的区别
如图: 输出结果是: 上面显示的是 ref 只是地址传递,所以最初改变的也只是地址,但是如果 在给其赋值,值会随之改变;如果 在方法内直接赋值,那么输出的结果 就是现在的值,之后 ...