分享
 
 
 

AIX 程序设计大赛---AIX正方形问题

王朝other·作者佚名  2007-09-18
窄屏简体版  字體: |||超大  

AIX 程序设计大赛---AIX正方形问题

作者:成晓旭

作为“算法及实现”栏目的“抛砖引玉”之作,将自己2年多前实现的一个算法放出来。有一年IBM出了这个Java程序设计竞赛题,当时,自己花晚上时间用Java实现了。

[问题描述]:

任意给定一个正方形,将正方形的各边做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

[设计简介]:

共设计3个类:

AixPoint:正方形问题的低层处理类,抽象正方形问题的每个访问点信息;

AixSquare:正方形问题的核心处理类,抽象正方形算法处理过程;

AixContest:正方形问题的客户调用处理类,抽象正方形问题的应用层。

[算法源码]:

AixPoint源码:

/** *//*******************************************************************************

* <<AIX 程序设计大赛---AIX正方形问题>>

* AIXContest ver1.0

* 开发作者: 成晓旭

* 项目简述: AIX程序设计的Java程序设计"AIX正方形问题"解决方案

* 启动时间: 2004年01月14日 20:00:08

* 完成时间: 2003年01月14日 20:09:00 <1个晚上>

*

* 开发环境: Windows2000 Professional + SUN J2SE1.4.2

* 开发工具: Rational Rose2002 Enterprise + JCreator2.5Pro

*

* 文件名称: AixPoint.java

* 简 介: 正方形问题的低层处理类,抽象正方形问题的每个访问点信息

*

* 备 注: <本系统的底层抽象>

*

* 修改时间1:

*

******************************************************************************/

package CXXSoft.Aix;

import java.awt.Point;

public class AixPoint extends Point

...{

private int moveUnit;

public boolean aheadExcess;

public boolean aboveExcess;

//类构造器

public AixPoint()

...{

aheadExcess = false;

aboveExcess = false;

moveUnit = 1;

}

//类构造器

public AixPoint(int x,int y)

...{

this();

this.x = x;

this.y = y;

}

//类构造器

public AixPoint(Point p)

...{

this();

this.x = p.x;

this.y = p.y;

}

//向左移动(前进)

public void goAhead()

...{

this.x += moveUnit;

}

//向左的反方向移动(后退)

public void goAheadReturn()

...{

this.x -= moveUnit;

}

//向上移动

public void goAbove()

...{

this.y += moveUnit;

}

//向上的反方向移动(后退)

public void goAboveReturn()

...{

this.y -= moveUnit;

}

//形成输出串

public String toString()

...{

return "("+ x + "," + y +")";

}

}

AixSquare源码:

/** *//*******************************************************************************

* <<AIX 程序设计大赛---AIX正方形问题>>

* AIXContest ver1.0

* 开发作者: 成晓旭

* 项目简述: AIX程序设计的Java程序设计"AIX正方形问题"解决方案

* 启动时间: 2004年01月14日 20:28:00

* 完成时间: 2003年01月17日 00:16:00<4个晚上>

*

* 开发环境: Windows2000 Professional + SUN J2SE1.4.2

* 开发工具: Rational Rose2002 Enterprise + JCreator2.5Pro

*

* 文件名称: AixSquare.java

* 简 介: 正方形问题的核心处理类,抽象正方形算法处理过程

*

* 备 注: <本系统的核心层抽象>

*

* 修改时间1:

*

* [问题描述]:

* 任意给定一个正方形,将正方形的各边做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

*

* [解答思路]:

* 此问题的核心是一个"有向无环图"的遍历问题,

* 解答的思想就是一个"试探"与"回溯"算法的抽象与实现.甚至比完整的

* "有向无环图"的遍历问题还要简单.

*

* [建模提示]:

* 为了简化问题的处理过程,强调解决问题的实质性思路,在建模过程中,

* 对遍历过程中每步"前进"的步长进行了"固定步长为1"的假设,即对将被

* n等分的正方形的边长,自动设置为n,以简化算法中对边的计算处理.

*

* [算法优化]:

* 目前设计的算法有以下几处有待优化:

* 1:此题是一般的"试探"与"回溯"算法一个特例,所以有些处理过程是可以省略的

* (目前实现的是一个标准的"试探"与"回溯"算法)

* 2:由于题目自身的特殊性,对某些处理过程可做简化,以提高算法的执行效率

* (如:对进栈,出栈的处理,对访问队列的处理,对在正方形边上"前进"时的

* 回溯处理,对临界条件,到达目标点条件的判断等等)

* 3:问题的本身及解答此题的思路是很具一般性的,但目前分析,设计的类结构过于特殊化.

*

******************************************************************************/

package CXXSoft.Aix;

import java.awt.Point;

import java.util.Stack;

import java.util.Vector;

import java.util.List;

import CXXSoft.Aix.AixPoint;

public class AixSquare

...{

//AIX正方形问题点遍历时前进方向常量定义

private final static int MOVE_AHEAD = 1; //向左

private final static int MOVE_ABOVE = 2; //向上

//AIX正方形问题点遍历时优先前进的方向常量定义

public final static int FIRST_MOVE_AHEAD = 101; //先从左至右,后从下向上

public final static int FIRST_MOVE_ABOVE = 102; //先从下向上,后从左至右

private int moveUnit; //当前算法处理的单位长度

private int nPart; //矩形边被等分的份数

private int firstMoveWay; //正方形问题线路优先前进方向

private int nAccess; //正确的通路总数

private Point startP;

private Point endP;

private String strPath;

private Vector visitedPoint; //遍历过程中已经访问过的点队列(每找到一条通道后被清空,然后重新加载)

private Stack visitStack; //遍历过程中的堆栈

private Vector rightAccess; //能到达目标点的正确通路队列

//算法访问的当前点

private AixPoint p;

private void visitPoint()

...{

if(strPath == null || strPath == "")

strPath = "Path" + (nAccess + 1) +": " + p;

else

strPath += " - " + p;

}

//判断是否向左前进越界

private boolean isAheadExcess()

...{

return (p.x > endP.x);

}

//判断是否向上前进越界

private boolean isAboveExcess()

...{

return (p.y > endP.y);

}

//将当前轮的遍历结果点组成的遍历线路存储于rightAccess中

private void saveArriveLine()

...{

String str = "",strAccess = "";

for(int i=0;i<visitedPoint.size();i++)

...{

AixPoint q = (AixPoint)visitedPoint.get(i);

str = (str == null || str == "") ? " Path" + (nAccess + 1) +": " : " - ";

strAccess += str + q;

}

rightAccess.add(strAccess);

}

//判断是否前进到目标点

private boolean isArriveAim()

...{

boolean isOK = false;

isOK = ((p.x == endP.x) && (p.y == endP.y)

&&(p.aheadExcess && p.aboveExcess));

if(isOK)

...{

saveArriveLine();

nAccess++;

strPath = "";

}

return isOK;

}

//遍历的当前点进栈

private void pushPoint()

...{

visitStack.push(p);

}

//遍历的当前点退栈

private void popPoint()

...{

if(!visitStack.empty())

...{

p = (AixPoint)visitStack.pop();

}

}

//修改遍历堆栈中,参数指定的点的越界标志

private void setVisitStackExcess(AixPoint para,int flag)

...{

for(int i=0;i<visitStack.size();i++)

...{

AixPoint q = (AixPoint)visitStack.get(i);

if(para == q)

...{

switch(flag)

...{

case MOVE_AHEAD:

q.aheadExcess = true;

break;

case MOVE_ABOVE:

q.aboveExcess = true;

break;

}

}

}

}

//遍历的当前点进入队列

private void enterList()

...{

visitedPoint.add(p);

}

//遍历的当前点退出队列(将当前点在遍历队列中删除)

private void exitList()

...{

visitedPoint.remove(p);

}

//修改遍历的当前点队列中,参数指定的点的越界标志

private void setVisitedListExcess(AixPoint para,int flag)

...{

for(int i=0;i<visitedPoint.size();i++)

...{

AixPoint q = (AixPoint)visitedPoint.get(i);

if(para == q)

...{

switch(flag)

...{

case MOVE_AHEAD:

q.aheadExcess = true;

break;

case MOVE_ABOVE:

q.aboveExcess = true;

break;

}

}

}

}

//判断当前点是否已经在曾经访问过的队列中

private boolean isVisited()

...{

boolean isExist = false;

for(int i=0;i<visitedPoint.size();i++)

...{

if(p == (AixPoint)visitedPoint.get(i))

...{

isExist = true;

break;

}

}

return isExist;

}

//AIX正方形问题的"尝试前进"方法

private void attempt(int flag)

...{

AixPoint q = new AixPoint(p);

p = q;

switch(flag)

...{

case MOVE_AHEAD:

//向左移动

p.goAhead(); //[向前尝试]

break;

case MOVE_ABOVE:

//向上移动

p.goAbove(); //[向上尝试]

}

}

//AIX正方形问题的"回溯后退"方法

private void backdate(int flag)

...{

popPoint(); //[向后/向下回溯]

pushPoint();

setVisitedListExcess(p,flag);

setVisitStackExcess(p,flag);

}

//新版:goAlwaysLeft()方法

protected void goAlwaysLeftNew()

...{

if(!isVisited())

...{

pushPoint();

enterList();

visitPoint();

}

attempt(MOVE_AHEAD);

if(isAheadExcess())

backdate(MOVE_AHEAD);

}

//新版:goAlwaysUpper()方法

protected void goAlwaysUpperNew()

...{

if(!isVisited())

...{

pushPoint();

enterList();

visitPoint();

}

attempt(MOVE_ABOVE);

if(isAboveExcess())

backdate(MOVE_ABOVE);

}

//成功找到一条通道后,回退到下一个正确的新起点方法

private void backdateNewStartPoint()

...{

while((p.aheadExcess && p.aboveExcess))

...{

if(p.x == startP.x && p.y == startP.y)

break;

popPoint();

if((p.x == endP.x) && (p.y == endP.y))

continue;

if(p.aheadExcess && !p.aboveExcess)

p.aboveExcess = true;

if(!p.aheadExcess && p.aboveExcess)

p.aheadExcess = true;

if((!p.aheadExcess && !p.aboveExcess))

...{

if((firstMoveWay == FIRST_MOVE_AHEAD) && (p.x <= startP.x))

...{

p.aheadExcess = true;

if(p.y >= endP.y)

p.aboveExcess = true;

}

if((firstMoveWay == FIRST_MOVE_ABOVE) && (p.y <= endP.y))

...{

p.aboveExcess = true;

if(p.x >= endP.x)

p.aheadExcess = true;

}

}

}

switch(firstMoveWay)

...{

case FIRST_MOVE_AHEAD:

p.aheadExcess = true;

break;

case FIRST_MOVE_ABOVE:

p.aboveExcess = true;

break;

}

pushPoint();

}

//成功找到一条通道后,从正确的新起点开始,将堆栈中所有的点转存入遍历队列

private void TransStackToNewList()

...{

visitedPoint.clear();

for(int i = 0; i < visitStack.size();i++)

visitedPoint.add(visitStack.get(i));

}

//正方形问题的沿当前线路前进的核心算法

private boolean advanceMoveKernel()

...{

switch(firstMoveWay)

...{

case FIRST_MOVE_AHEAD:

if(p.aheadExcess)

goAlwaysLeftNew();

else

goAlwaysUpperNew();

break;

case FIRST_MOVE_ABOVE:

if(p.aboveExcess)

goAlwaysUpperNew();

else

goAlwaysLeftNew();

break;

}

return isArriveAim();

}

//类构造器

public AixSquare()

...{

visitStack = new Stack();

visitedPoint = new Vector();

rightAccess = new Vector();

startP = new Point();

endP = new Point();

moveUnit = 1;

nAccess = 0;

strPath = "";

}

//类构造器

public void setProblemCondition(int part,int firstMove)

...{

this.firstMoveWay = firstMove;

if(part <= 0)

part = 1;

this.nPart = part;

endP.x = nPart;

endP.y = nPart;

nAccess = 0;

strPath = "";

visitStack.clear();

visitedPoint.clear();

rightAccess.clear();

}

//新版:正方形问题解答方法

public void solveProblemNew()

...{

boolean arriveAim = false;

p = new AixPoint(startP);

while(!p.aheadExcess || !p.aboveExcess)

...{

while(!p.aheadExcess || !p.aboveExcess)

...{

switch(firstMoveWay)

...{

case FIRST_MOVE_AHEAD:

if(!p.aheadExcess)

goAlwaysLeftNew();

else

goAlwaysUpperNew();

break;

case FIRST_MOVE_ABOVE:

if(!p.aboveExcess)

goAlwaysUpperNew();

else

goAlwaysLeftNew();

break;

}

arriveAim = isArriveAim();

if(arriveAim)

break;

}

backdateNewStartPoint();

TransStackToNewList();

if(visitStack.isEmpty() && (p.x == startP.x && p.y == startP.y))

break;

}

}

//类的处理结果输出串

public String toString()

...{

String str=" n = " + nPart;

for(int i=0;i<rightAccess.size();i++)

...{

str += rightAccess.get(i);

}

str += " Total = " + nAccess;

return str;

}

}

AixContest源码:

/** *//*******************************************************************************

* <<AIX 程序设计大赛---AIX正方形问题>>

* AIXContest ver1.0

* 开发作者: 成晓旭

* 项目简述: AIX程序设计的Java程序设计"AIX正方形问题"解决方案

* 启动时间: 2004年01月14日 20:00:00

* 完成时间: 2003年01月14日 23:16:00<3个晚上>

*

* 开发环境: Windows2000 Professional + SUN J2SE1.4.2

* 开发工具: Rational Rose2002 Enterprise + JCreator2.5Pro

*

* 文件名称: AixContest.java

* 简 介: 正方形问题的客户调用处理类,抽象正方形问题的应用层

*

* 备 注: <本系统的应用层抽象>

*

* 修改时间1:

*

* [问题描述]:

* 任意给定一个正方形,将正方形的各边做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

*

* [解答思路]:

* 此问题的核心是一个"有向无环图"的遍历问题,

* 解答的思想就是一个"试探"与"回溯"算法的抽象与实现.甚至比完整的

* "有向无环图"的遍历问题还要简单.

*

* [建模提示]:

* 为了简化问题的处理过程,强调解决问题的实质性思路,在建模过程中,

* 对遍历过程中每步"前进"的步长进行了"固定步长为1"的假设,即对将被

* n等分的正方形的边长,自动设置为n,以简化算法中对边的计算处理.

*

* [算法优化]:

* 目前设计的算法有以下几处有待优化:

* 1:此题是一般的"试探"与"回溯"算法一个特例,所以有些处理过程是可以省略的

* (目前实现的是一个标准的"试探"与"回溯"算法)

* 2:由于题目自身的特殊性,对某些处理过程可做简化,以提高算法的执行效率

* (如:对进栈,出栈的处理,对访问队列的处理,对在正方形边上"前进"时的

* 回溯处理,对临界条件,到达目标点条件的判断等等)

* 3:问题的本身及解答此题的思路是很具一般性的,但目前分析,设计的类结构过于特殊化.

******************************************************************************/

package CXXSoft.Aix;

import java.awt.Point;

import CXXSoft.Aix.AixSquare;

public class AixContest

...{

public static void main(String[] arg)

...{

System.out.println("AIX知识大赛初赛Java程序设计---AIX正方形问题");

AixSquare asProblem = new AixSquare();

String str="";

for(int i=1;i<=3;i++)

...{

asProblem.setProblemCondition(i,AixSquare.FIRST_MOVE_AHEAD);

asProblem.solveProblemNew();

str += asProblem + " ";

}

System.out.println(str);

System.out.println(" AIX正方形问题---运行结束......");

}

}

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有