商人过河问题(二)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. 了解设计 ...
随机推荐
- 《how to design programs》第11章自然数
这章让我明白了原来自然数的定义本来就是个递归的过程. 我们通常用枚举的方式引出自然数的定义:0,1,2,3,等等(etc).最后的等等是什么意思?唯一能把等等从描述自然数的枚举方法中去除的方法是自引用 ...
- 常用数据结构及复杂度 array、LinkedList、List、Stack、Queue、Dictionary、SortedDictionary、HashSet、SortedSet
原文地址:http://www.cnblogs.com/gaochundong/p/data_structures_and_asymptotic_analysis.html 常用数据结构的时间复杂度 ...
- 如何区分监督学习(supervised learning)和非监督学习(unsupervised learning)
监督学习:简单来说就是给定一定的训练样本(这里一定要注意,样本是既有数据,也有数据对应的结果),利用这个样本进行训练得到一个模型(可以说是一个函数),然后利用这个模型,将所有的输入映射为相应的输出,之 ...
- Linux进程笔记
进程及作业管理 Uninterruptible sleep: 不可中断的睡眠Interruptible sleep:可中断睡眠 kernel:init: COW: Copy On Write, 写时复 ...
- VMware 虚拟机的网络连接方式详解
VMWare提供了三种工作模式,它们是bridged(桥接模式).NAT(网络地址转换模式)和host-only(主机模式).要想在网络管理和维护中合理应用它们,你就应该先了解一下这三种工作 ...
- Java凝视Annotation
Java凝视Annotation 从JDK 5開始,Java添加了对元数据(MetaData)的支持,也就是Annotation(凝视).Annotation提供了一种为程序元素设置元数据的方法 ...
- Zero Downtime Upgrade of Oracle 10g to Oracle 11g Using GoldenGate — 2
Prepare 10g Database for OGG Create GGS and GGS_MON Database Users SQL> create tablespace ggs_tbs ...
- Cocos2d-x游戏开发CCBAnimationManager控制动画
CocosBuilder能方便的编辑各种动画.大部分动画都是以独立片段的形式存在的. 须要由程序来控制何时播放. 管理ccbi文件的动画播放有个专门的类:CCBAnimationManager 大致的 ...
- PPTP协议握手流程分析
一 PPTP概述 PPTP(Point to Point Tunneling Protocol),即点对点隧道协议.该协议是在PPP协议的基础上开发的一种新的增强型安全协议,支持多协议虚拟专用网,可 ...
- bach cello
http://bachlb.blog.163.com/blog/static/1819105120073275251223 一个偶然的机会,卡萨尔斯的父亲来巴塞罗那看卡萨尔斯,并且一起去逛了一间海边的 ...