商人过河问题(二)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. 了解设计 ...
随机推荐
- synchronized常见用法解析及示例
synchronized作用:保证代码执行的原子性:保证可见性(与volatile作用相同) JAVA中synchronized关键字能够作为函数的修饰符,也可作为函数内的语句,也就是平时说的同步方法 ...
- ubuntu centos debina
文章目录CentOSDebianCentOS与Debian哪个好?Ubuntu买VPS时有CentOS.Debian.Ubuntu三种操作系统可以选择,Linux下哪种系统更好是很多新人都会遇到的问题 ...
- 【转】RTSP流理解
rtsp是使用udp还是tcp,是跟服务器有关,服务器那边说使用udp,那就使用udp,服务器说使用tcp那就使用tcp rtsp客户端的创建: 1.建立TCP socket,绑定服务器ip,用来传送 ...
- 解读JavaScript代码 var ie = !-[1,]
var ie = !-[1,]: 这句代码在IE9之前曾被称为世界上最短的IE判定代码.代码虽短但确包含了不少javascript基础知识在里面.在这个例子中代码执行时会先调用数组的toString( ...
- 《JavaScript 闯关记》之表达式和运算符
表达式 表达式是由数字.运算符.数字分组符号(如括号).自由变量和约束变量等以能求得数值的有意义排列方法所得的组合.JavaScript 表达式主要有以下几种形式: 原始表达式:常量.变量.保留字. ...
- 求1+2+3+...+n的值,要求不能使用乘除法,for、while、if、else、switch、case、等关键字及条件判断语句(JAVA)
采用递归和三目表达式注意红色字体一定不能写成n-- 1 package com.hunag; public class Sum { static int sum; public static int ...
- Method to fix "Naming information cannot be located because the target principal name is incorrect." for AD replication failure
Assume Failure DC FP01 and Working DC DC01 1. Stop the Key Distribution Center (KDC) service on FP01 ...
- IT技术论坛
http://www.v2ex.com/ http://www.dewen.org/ http://stackoverflow.com/ http://segmentfault.com/ 博客园
- FullScreenFragment Code
package com.dexode.fragment; import android.annotation.TargetApi; import android.app.Activity; impor ...
- strace排除Linux服务器故障
strace是一个有用的小工具 – 大多数Linux系统默认已经安装 – 可以通过跟踪系统调用来让你知道一个程序在后台所做的事情.Strace是一个基础的调试工具;但是即便你不是在跟踪一个问题的时候它 ...