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

news/2025/2/22 16:52:31

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源码:

/*******************************************************************************
 *    < >
 *            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源码:

/*******************************************************************************
 *    < >
 *            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源码:

 

/*******************************************************************************
 *    < >
 *            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正方形问题---运行结束......");
    }

}




http://www.niftyadmin.cn/n/3649184.html

相关文章

bootstrap4侧边栏_如何使用纯CSS和Bootstrap 4构建多个堆叠式粘性侧边栏

bootstrap4侧边栏In this tutorial you’ll work on building multiple sticky sidebars that stack without using any JavaScript. 在本教程中&#xff0c;您将构建无需使用任何JavaScript即可堆叠的多个粘性侧栏。 We’ll discuss: 我们将讨论&#xff1a; Multiple Stack…

textView相关知识

一、给textview设置颜色为#fffff 有时候我们会从服务器获得数据&#xff0c;但是后台给的服务器的值是比如&#xff1a;#B373FB 此时要想给TextView设置文字直接设置textview.setTextColor();是不行的。此时我们可以这样 String str floorcolor; int id Color.parseColor(s…

PYthon 转换HTML到Text纯文本

今天项目需要将HTML转换为纯文本&#xff0c;去网上搜了一下&#xff0c;发现Python果然是神通广大&#xff0c;无所不能&#xff0c;方法是五花八门。。。 拿今天亲自试的两个方法举例&#xff0c;以方便后人&#xff1a; 方法一&#xff1a; 1. 安装nltk&#xff0c;可以去…

如何使用vue-router设置Vue.js身份验证和路由处理

介绍 (Introduction) Vue.js is a progressive JavaScript framework for building front-end applications. Coupled with vue-router, we can build high performance applications with complete dynamic routes. Vue-router is an efficient tool and can efficiently hand…

Delphi之东进模拟语音卡(D160A)可复用源码

Delphi之东进模拟语音卡(D160A)可复用源码作者&#xff1a;成晓旭Blog&#xff1a;http://blog.csdn.net/cxxsoft(声明&#xff1a;欢迎转载&#xff0c;请保证文章的完整性)设计简介&#xff1a;1、 将卡、通道分别单独进行设计与封装。2、 所有的外部操作接口都封装在卡类…

友盟多渠道打包

1.按照umeng的要求&#xff0c;manifest文件中需要有 这段配置&#xff0c;value那里就是wandoujia&#xff0c;360之类的渠道名称&#xff0c;但是我们在这里不会去写渠道名&#xff0c;写的是一个占位符&#xff0c;后面gradle编译的时候会动态的替换掉它。 <meta-dataa…

Django出现的'ascii' codec can't encode characters in position...的解决办法

昨天买了服务器空间&#xff0c;由于服务器在国外&#xff0c;操作系统是英文版的Ubuntu11&#xff0c;多多少少会遇到编码的问题 今天遇到的问题是上传一个带有中文名的照片的时候&#xff0c;出现了以下错误&#xff1a;“ascii codec cant encode characters in position 5…

ios pusher使用_如何使用Laravel和Pusher通道创建Web通知

ios pusher使用Many web applications include an in-app notification system that will notify you instantly when someone carries out an action related to you or your account. On Facebook, you will be notified when someone likes your status, or when someone co…