本文实现的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实现的更多相关文章

  1. 实验二 Java面向对象程序设计

    实验二 Java面向对象程序设计 实验内容 1. 初步掌握单元测试和TDD 2. 理解并掌握面向对象三要素:封装.继承.多态 3. 初步掌握UML建模 4. 熟悉S.O.L.I.D原则 5. 了解设计 ...

  2. 20145213《Java程序设计》实验二Java面向对象程序设计实验报告

    20145213<Java程序设计>实验二Java面向对象程序设计实验报告 实验内容 初步掌握单元测试和TDD 理解并掌握面向对象三要素:封装,继承,多态 初步掌握UML建模 熟悉S.O. ...

  3. 20145206《Java程序设计》实验二Java面向对象程序设计实验报告

    20145206<Java程序设计>实验二Java面向对象程序设计实验报告 实验内容 初步掌握单元测试和TDD 理解并掌握面向对象三要素:封装.继承.多态 初步掌握UML建模 熟悉S.O. ...

  4. 20145308刘昊阳 《Java程序设计》实验二 Java面向对象程序设计 实验报告

    20145308刘昊阳 <Java程序设计>实验二 Java面向对象程序设计 实验报告 实验名称 Java面向对象程序设计 实验内容 初步掌握单元测试和TDD 理解并掌握面相对象三要素:封 ...

  5. 20145113 实验二 Java面向对象程序设计

    20145113 实验二 Java面向对象程序设计 实验内容 初步掌握单元测试和TDD 理解并掌握面向对象三要素:封装.继承.多态 初步掌握UML建模 熟悉S.O.L.I.D原则 了解设计模式 1.初 ...

  6. JAVA课程实验报告 实验二 Java面向对象程序设计

    北京电子科技学院(BESTI) 实     验    报     告 课程:Java程序设计  班级:1353  姓名:韩玉琪  学号:20135317 成绩:             指导教师:娄嘉 ...

  7. 20145225唐振远 实验二 "Java面向对象程序设计"

    20145225<Java程序设计> 实验二 Java面向对象程序设计 实验报告 实验内容 初步掌握单元测试和TDD 理解并掌握面向对象三要素:封装.继承.多态 初步掌握UML建模 熟悉S ...

  8. 20145208 实验二 Java面向对象程序设计

    20145208 实验二 Java面向对象程序设计 实验内容 初步掌握单元测试和TDD 理解并掌握面向对象三要素:封装.继承.多态 初步掌握UML建模 熟悉S.O.L.I.D原则 了解设计模式 实验步 ...

  9. 20162311 实验二 Java面向对象程序设计 实验报告

    实验二 Java面向对象程序设计 实验内容 1. 初步掌握单元测试和TDD 2. 理解并掌握面向对象三要素:封装.继承.多态 3. 初步掌握UML建模 4. 熟悉S.O.L.I.D原则 5. 了解设计 ...

随机推荐

  1. 【转】 linux内核移植和网卡驱动(二)

    原文网址:http://blog.chinaunix.net/uid-29589379-id-4708911.html 一,内核移植步骤: 1, 修改顶层目录下的Makefile ARCH       ...

  2. Jquery之家5个顶级Material Design框架

    谷歌Material Design在如今的前端页面设计中非常流行.Material Design的设计风格向我们展示了一个简单而有内涵的现代UI设计方案. Material Design是如此的简洁美 ...

  3. 百度地图V1.5 LocalSearch增加浮动窗体的操作内容

     1.初始化LocalSearch控件 LocalSearch = new BMap.LocalSearch(map, { renderOptions : { map : map, panel : & ...

  4. hdu 4501 小明系列故事——买年货_二维背包

    题目:你可以有v1元,v2代金券,v3个物品免单,现在有n个商品,商品能用纸币或者代金券购买,当然你可以买v3个商品免费.问怎么最大能买多少价值 题意: 思路二维背包,dp[v1][v2][v3]=M ...

  5. 在国内使用cnpm代替npm

    npm是Node.js的模块依赖管理工具,由于使用npm安装包是从国外服务器下载,在国内很容易受到网络的影响,速度非常慢,因此可以选用cnpm.cnpm可以使用淘宝团队提供的淘宝npm镜像,你可以用此 ...

  6. hdu 2438 Turn the corner(几何+三分)

    Problem Description Mr. West bought a new car! So he is travelling around the city. One day he comes ...

  7. 对数组元素进行排序的方法总结(利用C++)

    首先,对数组元素进行排序方法总结为以下两类: 一.简单排序算法(时间复杂度O(n*n)) 1.插入排序 2.选择排序 3.交换排序,即冒泡排序 二.先进排序算法(时间复杂度O(n*logn)) 1.快 ...

  8. LightOJ 1338 && 1387 - Setu && LightOJ 1433 && CodeForces 246B(水题)

    B - B Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%lld & %llu Submit Status P ...

  9. vb.NET基础总结

    vb.NET语言的学习,相对于原来的添加了.net平台,也 是基于对vb学习的继承与扩展,是在面向对象基础上的编程语言,vb中学到的控制语句,主要的数据类型,对象的事件,方法,属性等继续应用于vb.n ...

  10. 深入浅出:重温JAVA中接口与抽象的区别

    抽象类:声明一个抽象类,就是在类的声明开头.在Class关键字的前面使用关键字abstract 下面定义一个抽象类,代码如下: abstract class A{ abstract void call ...