您的位置:首页 > 大数据 > 人工智能

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

2008-04-10 02:50 459 查看
AIX 程序设计大赛---AIX正方形问题[b]作者:成晓旭[/b]作为“算法及实现”栏目的“抛砖引玉”之作,将自己2年多前实现的一个算法放出来。有一年IBM出了这个Java程序设计竞赛题,当时,自己花晚上时间用Java实现了。[问题描述]:任意给定一个正方形,将正方形的各边做n等分,并将相应各点连接成水平或垂直的直线,如果从正方形的左下角(0,0)出发,沿各边线或连接线,自左向右或自下而上的方向,到达正方形的右上角(n,n),请用JAVA程序计算并输出所有可能的路径总数和具体线路.请提供相关JAVA源程序和n=2,3,4时的输出结果。输出结果按以下方式:以n=1为例:n = 1Path1: (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



        ...{


            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



        ...{


            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



        ...{


            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



        ...{


            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



        ...{


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


    }


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