您的位置:首页 > 编程语言 > Java开发

AIX 程序设计大赛-AIX正方形问题算法及Java程序实现(方案二)

2006-09-08 02:24 966 查看
今天又对前天所实现的《AIX 程序设计大赛-AIX正方形问题》解决方案进行了改善,同时又找到了一条崭新的解决方案,没想到效果比想象中的要好,这一篇描述改良方案的算法思路及实现,下一篇介绍一个新的思路更简洁的方案。

为了文章的完整性,本篇仍然包括问题描述部分。

问题描述:
任意给定一个正方形,将正方形的各边做n等分,并将相应各点连接成水平或垂直的直线,如果从正方形的左下角(0,0)出发,沿各边线或连接线,自左向右或自下而上的方向,到达正方形的右上角(n,n),请用JAVA程序计算并输出所有可能的路径总数和具体线路.请提供相关JAVA源程序和n=2,3,4时的输出结果。输出结果按以下方式:

以n=1为例:
n = 1
Path1: (0,0) - (0,1) - (1,1)
Path2: (0,0) - (1,0) - (1,1)
Total = 2

解决思路:
上篇回顾
上一篇文章中的解决思路,为通过采用“向上优先”策略,发现通过上一条路径可以直接推导出下一条路径,在这个推导过程中,定义了两个关键点,一个命名为上一条路径的“顶极点”,一个命名为下一条路径的“突破点”,并发现这两个点之间的关系:

第一种:若顶极点为上边点,则按照向上优先策略,突破点和顶极点关系为:
breakPoint.x = tipPolePoint.x+1
breakPoint.y = tipPolePoint.y-1

第二种:若顶极点为右边点,则按照向上优先策略,突破点和顶极点关系为:
breakPoint.x = (min(x)|y=tipPolePoint.y)+1
breakPoint.y = tipPolePoint.y-1

思路优化
通过进一步的分析,发现以上描述的突破点和顶极点的两种关系,最核心的其实是“最后右拐点”,通过最后右拐点我们既可以简化(上一条路径)顶极点的查找,又可以简化(下一条路径)突破点的推导。
最后右拐点定义:既一条路径中最有一次向右拐弯的那个点。

依然按照向上优先侧略,下一条路径的突破点和上一条路径的最后右拐点,之间的关系为:
设:最后右拐点为lastRightTurnPoint,突破点为breakPoint。则有
breakPoint.x = lastRightTurnPoint.x+1
breakPoint.y = lastRightTurnPoint.y-1

算法特点
由于该算法统一了第一种算法中突破点推导的两种方法,简化了推导过程,所以思路更加清晰、效率更加高效。

程序设计:
和以上算法设计类似,这个算法的实现也包括三个类,分别简述如下:
Point:基础类,表示坐标点,和第一方案相同;
AixUtil2:工具类,按照向上优先策略,提供解决AIX正方形问题的一些静态方法,是第一方案的优化;
AixClient:一个简单的调用类,可同时测试方案一(调用AixUtil)和方案二(调用AixUtil2)。

源程序代码如下:
Point:基础类,表示坐标点;

package qinysong.aix;

/**
* <p>Title: 基础类,表示坐标点</p>
* <p>Description: AIX 程序设计大赛---AIX正方形问题</p>
* <p>Copyright: Copyright (c) 2006</p>
* <p>Company: qinysong</p>
* @author zhaoqingsong
* @version 1.0 $Date: 2006/09/05 21:44:36 $
*/

public class Point {
protected int x;
protected int y;

/**
* 构造函数
* @param x int
* @param y int
*/
public Point(int x, int y){
this.x = x;
this.y = y;
}

public String toString(){
return "(" + x + "," + y + ")";
}

/**
* 判断是否为上边点
* @return boolean
*/
public boolean isTopBorderPoint(int nValue){
return this.y == nValue;
}

/**
* 判断thePoint是否与自己相等
* @param thePoint Point
* @return boolean
*/
public boolean equals(Point thePoint){
return (this.x == thePoint.x) && (this.y == thePoint.y);
}

}

AixUtil2:工具类,按照向上优先策略,提供解决AIX正方形问题的一些静态方法,是第一方案的优化

package qinysong.aix;

/**
* <p>Title: 工具类,按照向上优先策略,提供解决AIX正方形问题的一些静态方法</p>
* <p>Description: AIX 程序设计大赛---AIX正方形问题</p>
* <p>Copyright: Copyright (c) 2006</p>
* <p>Company: qinysong</p>
* @author zhaoqingsong
* @version 1.0 $Date: 2006/09/05 21:52:18 $
*/

public class AixUtil2 {

private static int nValue;
private static int laseRightTurnIndex;
private static Point[] squarePoints= null;

/**
* 初始化正方形边长
* @param nValue int
*/
public static void initNValue(int nValue) {
if (nValue <= 0) {
throw new RuntimeException("初始化正方形边长异常,长度不能小于等于零");
}
AixUtil2.nValue = nValue;
squarePoints = new Point[(nValue+1)*(nValue+1)];
for (int y = 0; y <= nValue; y++){
for (int x = 0; x <= nValue; x++){
squarePoints[y*(nValue+1)+x] = new Point(x,y);
}
}
}

/**
* <p>取得上一条路径的最后右拐点</p>
* <p>最后右拐点:在到达最后顶点point(n,n)之前的最后一个向右拐的点<br>
*
* @param previousPathPoints Point[] 上一条路径节点数组
* @return Point tipPolePoint顶极点
*/
public static Point getLastRightTurnPoint(Point[] previousPathPoints) {
Point lastRightTurnPoint = null;
int index = 2*nValue;
while (previousPathPoints[index].x == nValue
|| previousPathPoints[index].y == previousPathPoints[index-1].y){
index--;
}
laseRightTurnIndex = index;
lastRightTurnPoint = previousPathPoints[index];
return lastRightTurnPoint;
}

/**
* <p>取得下一条路径的突破点,返回的突破点定义为breakPoint<br>
* 通过几何数学分析,按照向上优先策略,有如下突破点和上一条路径的最后右拐点的关系<br>
* breakPoint.x = lastRightTurnPoint.x+1<br>
* breakPoint.y = lastRightTurnPoint.y-1</p>
*
* @param lastRightTurnPoint Point 最后右拐点,表示上一条路径的最后右拐点
* @return Point 返回下一条路径的突破点 breakPoint
*/
public static Point getBreakPoint(Point lastRightTurnPoint) {
int index = (lastRightTurnPoint.y - 1)*(nValue+1)+lastRightTurnPoint.x + 1;
Point breakPoint = squarePoints[index];
return breakPoint;
}

/**
* 按照向上优先策略(即能往上走就往上走),取得下一个路径节点
* @param currentPoint Point
* @return Point 下一个路径节点
*/
public static Point getNextPoint(Point currentPoint) {
int index = 0;
if (currentPoint.y < nValue) {
index = (currentPoint.y + 1)*(nValue+1)+currentPoint.x;
} else if (currentPoint.x < nValue) {
index = (currentPoint.y)*(nValue+1)+currentPoint.x + 1;
} else {
return null;
}
return squarePoints[index];
}

/**
* 按照向上优先策略(即能往上走就往上走),取得下一条路径节点
* @param previousPathPoints Point[] 上一条路径节点
* @return Point[] 下一条路径
*/
public static Point[] getNextPath(Point[] previousPathPoints) {
int arrayLength = 2*nValue+1;
Point lastRightTurnPoint = getLastRightTurnPoint(previousPathPoints);
Point breakPoint = getBreakPoint(lastRightTurnPoint);
Point[] nextPath = new Point[arrayLength];
int index = 0;
for (; index < laseRightTurnIndex; index++) {
nextPath[index] = previousPathPoints[index];
}
nextPath[index++] = breakPoint;
Point tempPoint = breakPoint;
while ( (tempPoint = getNextPoint(tempPoint)) != null) {
nextPath[index++] = tempPoint;
}
return nextPath;
}

/**
* 按照向上优先策略,取得第一条路径
* @return Point[]
*/
public static Point[] getFirstPath() {
Point[] firstPath = new Point[2*nValue+1];
for (int i = 0; i <= nValue; i++) {
firstPath[i] = squarePoints[i*(nValue+1)];
}
for (int i = 1; i <= nValue; i++) {
firstPath[nValue + i] = squarePoints[nValue*(nValue+1)+i];
}
return firstPath;
}

/**
* <p>按照向上优先策略(即能往上走就往上走),取得下一条路径节点<br>
* 这个函数是上面getNextPath和getFirstPath的合并,用以得到整体的下一条路径<br>
* 如果previousPathPoints 为空,则取得第一条路径<br>
* 如果previousPathPoints不为空,则根据其取得下一条路径</p>
* @param previousPathPoints Point[] 上一条路径节点
* @return Point[] 下一条路径
*/
public static Point[] getTotalNextPath(Point[] previousPathPoints) {
if (previousPathPoints == null){
return getFirstPath();
} else {
return getNextPath(previousPathPoints);
}
}

/**
* 判断是否是最后一条路径
* @param pathPoints Point[]
* @return boolean
*/
public static boolean isLastPath(Point[] pathPoints){
int middleIndex = nValue;
return pathPoints[middleIndex].y == 0;
}

/**
* 按照题目要求格式打印一条路径的节点
* @param pathNumber int
* @param pathPoints Point[]
*/
public static void printlnPathPoints(int pathNumber, Point[] pathPoints) {
StringBuffer pathStringBuffer = new StringBuffer();
pathStringBuffer.append("Path" + pathNumber + ":");
int arrayLength = 2*nValue+1;
for (int i = 0; i < arrayLength; i++) {
pathStringBuffer.append(pathPoints[i].toString() + "-");
}
String pathString = pathStringBuffer.toString();
if (pathString.length()>0) pathString = pathString.substring(0,pathString.length()-1);
System.out.println(pathString);
}

}

AixClient:一个简单的调用类,可同时测试方案一(调用AixUtil)和方案二(调用AixUtil2)

package qinysong.aix;

import java.util.Date;

/**
* <p>Title: 调用类,该类通过工具类AixUtil提供的方法,遍历一个正方形的路径</p>
* <p>Description: AIX 程序设计大赛---AIX正方形问题</p>
* <p>Copyright: Copyright (c) 2006</p>
* <p>Company: qinysong</p>
* @author zhaoqingsong
* @version 1.0 $Date: 2006/09/05 22:49:22 $
*/

public class AixClient {

public static void main(String[] args) {
System.out.println("AixClient.main begin ......");
System.out.println("AixClient.main 方案1");
Date beginTime1 = new Date();
System.out.println("beginTime1:" + beginTime1.toString());
int nValue = 5;
Point[] pathPoints = null;
int pathNumber = 0;
System.out.println("当n=" + nValue);
AixUtil.initNValue(nValue);
do {
pathPoints = AixUtil.getTotalNextPath(pathPoints);
++pathNumber;
AixUtil.printlnPathPoints(pathNumber, pathPoints);
}while (!AixUtil.isLastPath(pathPoints));
System.out.println("Total:" + pathNumber);
Date endTime1 = new Date();
System.out.println("end endTime1 : " + endTime1.toString());

System.out.println("AixClient.main 方案2");
Date beginTime2 = new Date();
System.out.println("beginTime2:" + beginTime2.toString());
System.out.println("当n=" + nValue);
AixUtil2.initNValue(nValue);
pathPoints = null;
pathNumber = 0;
do {
pathPoints = AixUtil2.getTotalNextPath(pathPoints);
++pathNumber;
AixUtil2.printlnPathPoints(pathNumber, pathPoints);
}while (!AixUtil2.isLastPath(pathPoints));
System.out.println("Total:" + pathNumber);
Date endTime2 = new Date();
System.out.println("end endTime2 : " + endTime2.toString());
System.out.println("方案1所花时间毫秒: " + (endTime1.getTime() - beginTime1.getTime()));
System.out.println("方案2所花时间毫秒: " + (endTime2.getTime() - beginTime2.getTime()));

System.out.println("AixClient.main end ......");
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: