上次貼的代碼不對,這次更新了一下
下載

/**
    滑雪Description
    Time Limit: 1000MS  Memory Limit: 65536K 
    Total Submissions: 27578  Accepted: 9545 
    
    Michael喜歡滑雪百這并不奇怪, 因為滑雪的確很刺激。可是為了獲得速度,滑的區(qū)域必須向下傾斜,而且當(dāng)你滑到坡底,你不得不再次走上坡或者等待升降機來載你。
    Michael想知道載一個區(qū)域中最長底滑坡。區(qū)域由一個二維數(shù)組給出。數(shù)組的每個數(shù)字代表點的高度。下面是一個例子 
    
    
     1  2  3  4  5
    16 17 18 19  6
    15 24 25 20  7
    14 23 22 21  8
    13 12 11 10  9
    
    一個人可以從某個點滑向上下左右相鄰四個點之一,當(dāng)且僅當(dāng)高度減小。在上面的例子中,一條可滑行的滑坡為24-17-16-1。當(dāng)然25-24-23--3-2-1更長。事實上,這是最長的一條。
    
    Input
    輸入的第一行表示區(qū)域的行數(shù)R和列數(shù)C(1 <= R,C <= 100)。下面是R行,每行有C個整數(shù),代表高度h,0<=h<=10000。
    
    Output
    輸出最長區(qū)域的長度。
    
    Sample Input
    5 5
     1  2  3  4  5
    16 17 18 19  6
    15 24 25 20  7
    14 23 22 21  8
    13 12 11 10  9
    
    
    Sample Output
    25
 
*/

/**
 * 得考慮到有相同高度的點,所以中途應(yīng)該記錄坐標(biāo)
 * 最高點與最低點可以有多個,但是假設(shè):終點只有一個,就是第一個最低的點。出發(fā)點只有一個,第一個最高的點。
 
*/

public class Skee {
    
public int xw,yw;//矩陣的長與寬
    
    
//前兩維索引是點坐標(biāo),最后一維:
    
//[0]當(dāng)前點的高度 [1]是否(1|0)曾到達過該點 [2,3]當(dāng)前最佳上一點坐標(biāo)y,x [4]當(dāng)前到該步為止最佳路徑長度 
    
//[5,6][7,8][9,10][11,12]分別為上下左右下一步的點的坐標(biāo),若為(-1,-1)則該點對應(yīng)方向不可以走,或者該點還未向四周滑動
    public int[][][] ptInfos;//[y][x][13]    
    
//[0] 高度 [1]是1否0己有父坐標(biāo) [2,3]當(dāng)前最遠路徑父坐標(biāo)y,x [4]路徑長度 [5,6][7,8][9,10][11,12]分別為上下左右下一步坐標(biāo)
    
    
//存儲當(dāng)前輪可以滑動的點以及下一輪可以滑動的點
    
//[點數(shù)][3] 第二維的三分別為:Index0值:0該點未使用或己作廢,1本輪可向四周滑動的點,2本輪新加入的點_下一輪才能向四周滑動 (Index1,Index2)點坐標(biāo) 
    public int[][] ptNowStep;
    
int ptNowStepTop = 0;//當(dāng)前使用到的位置的頂部,可以理解為棧頂?shù)囊馑及?/span>
    int ptNowStepIndex;//一個可以利用的存新的未走過的點的位置
    int ptNowStepRecycle = -1;//最后一個回收的點
    
    
int Point_StartX, Point_StartY, Point_EndX, Point_EndY;//出發(fā)點與終點的坐標(biāo)
    int xNow, yNow, xNext, yNext, hNow;//當(dāng)前點的坐標(biāo)、下一步的坐標(biāo)、當(dāng)前點的高度
    boolean canNextStep;//己加入新的未走過的點,需要繼續(xù)滑
    
    
public int[] hightPath;
    
    
//pts矩陣,存儲各坐標(biāo)點對應(yīng)的高度
    public Skee(int[][] pts) {
        yw 
= pts.length;
        xw 
= pts[0].length;
        ptInfos 
= new int[yw][xw][13];
        ptNowStep 
= new int[yw * xw][3];
        
for (int y = 0; y < yw; y++{
            
for (int x = 0; x < xw; x++{
                ptInfos[y][x][
0= pts[y][x];
                
for (int i = 5; i <= 12; i++{
                    ptInfos[y][x][i] 
= -1;
                }

            }

        }

        
        
//找到出發(fā)點與終點
        int valStart = 0, valEnd = 10001;
        
for (int y = 0; y < yw; y++{
            
for (int x = 0; x < xw; x++{
                
if (ptInfos[y][x][0< valEnd) {
                    valEnd 
= ptInfos[y][x][0];
                    Point_EndX 
= x;
                    Point_EndY 
= y;
                }
 else if (ptInfos[y][x][0> valStart) {
                    valStart 
= ptInfos[y][x][0];
                    Point_StartX 
= x;
                    Point_StartY 
= y;
                }

            }

        }

        
        
//初始化出發(fā)點
        ptInfos[Point_StartY][Point_StartX][4= 1;
        ptNowStepIndex 
= get_ptNowStepIndex();
        ptNowStep[ptNowStepIndex][
0= 1;
        ptNowStep[ptNowStepIndex][
1= Point_StartY;
        ptNowStep[ptNowStepIndex][
2= Point_StartX;
    }

    
    
//開始計算路徑
    public void computePath() {
        
while(nextStep());
    }

    
    
    
//返回最長步數(shù)(實際是點數(shù))
    public int getMatStep() {
        
return ptInfos[Point_EndY][Point_EndX][4];
    }

    
    
//打印出最長步數(shù)的所有點高度
    public void printMaxStep() {
        
int top = xw*yw - 1;
        
int x = Point_EndX;
        
int y = Point_EndY;
        
int tmp;
        hightPath 
= new int[xw*yw];
        
while (ptInfos[y][x][1== 1{
            hightPath[top
--= ptInfos[y][x][0];
            tmp 
= y;
            y 
= ptInfos[tmp][x][2];
            x 
= ptInfos[tmp][x][3];
        }

        hightPath[top
--= ptInfos[y][x][0];
        top
++;
        System.out.print(hightPath[top
++]);
        
for (int i = top; i < hightPath.length; i++{
            System.out.print(
"->" + hightPath[i]);
        }

        System.out.println();
    }

    
    
//取一個ptNowStep的index用于保存需要擴展的點
    private int get_ptNowStepIndex() {
        
if (ptNowStepRecycle != -1{
            
int tmp = ptNowStepRecycle;
            ptNowStepRecycle 
= -1;
            
return tmp;
        }

        
for (int i = 0; i < ptNowStep.length; i++{
            
if (ptNowStep[i][0== 0{
                
if (i >= ptNowStepTop) {
                    ptNowStepTop 
= i + 1;
                }

                
return i;
            }

        }

        
return -1;//不會走到,除非程序有問題
    }

    
    
private boolean nextStep() {
        
int ptNowStepTopTmp = ptNowStepTop;
        canNextStep 
= false;
        
for (int i = 0; i < ptNowStepTopTmp; i++{
            
if (ptNowStep[i][0!= 1{
                
continue;
            }
 else if (ptNowStep[i][1== Point_EndY && ptNowStep[i][2== Point_EndX) {
                ptNowStep[i][
0= 0;
                
continue;
            }

            xNow 
= ptNowStep[i][2];
            yNow 
= ptNowStep[i][1];
            hNow 
= ptInfos[yNow][xNow][0];
            
//向上滑
            xNext = xNow;
            yNext 
= yNow - 1;
            
if (yNext >= 0 && hNow > ptInfos[yNext][xNext][0]) {
                stepInto(
0);
            }

            
//向下滑
            yNext = yNow + 1;
            
if (yNext < yw && hNow > ptInfos[yNext][xNext][0]) {
                stepInto(
1);
            }

            
//向左滑
            yNext = yNow;
            xNext 
= xNow - 1;
            
if (xNext >= 0 && hNow > ptInfos[yNext][xNext][0]) {
                stepInto(
2);
            }

            
//向右滑
            xNext = xNow + 1;
            
if (xNext < xw && hNow > ptInfos[yNext][xNext][0]) {
                stepInto(
3);
            }

            ptNowStep[i][
0= 0;
            ptNowStepRecycle 
= i;
        }

        
if (canNextStep) {
            
for (int i = 0; i < ptNowStepTop; i++{
                
if (ptNowStep[i][0== 2{
                    ptNowStep[i][
0= 1;
                }

            }

            
return true;
        }

        
return false;
    }

    
    
//向前滑一步 dir=0123:上下左右
    private void stepInto(int dir) {
        
//本步的子指向更新
        ptInfos[yNow][xNow][5 + dir * 2= yNext;
        ptInfos[yNow][xNow][
6 + dir * 2= xNext;
        
if (ptInfos[yNow][xNow][4>= ptInfos[yNext][xNext][4]) {//可以得到更多的步數(shù),則更新
            
//下一步的父指向更新
            ptInfos[yNext][xNext][2= yNow;
            ptInfos[yNext][xNext][
3= xNow;
            ptInfos[yNext][xNext][
4= ptInfos[yNow][xNow][4+ 1;
            
if (ptInfos[yNext][xNext][1== 1//先前己探索,更新子孫路徑長度
                updateSubPathLen(yNext, xNext);
            }
 else {
                ptInfos[yNext][xNext][
1= 1;
                ptNowStepIndex 
= get_ptNowStepIndex();
                ptNowStep[ptNowStepIndex][
0= 2;
                ptNowStep[ptNowStepIndex][
1= yNext;
                ptNowStep[ptNowStepIndex][
2= xNext;
                canNextStep 
= true;
            }

        }

    }

    
    
//更新后繼步的步數(shù)
    private void updateSubPathLen(int y, int x) {
        
int ysub, xsub;
        
int pathLenSub = ptInfos[y][x][4+ 1;
        
for (int i = 0; i < 4; i++{
            ysub 
= ptInfos[y][x][5 + i * 2];
            xsub 
= ptInfos[y][x][6 + i * 2];
            
if (ysub != -1 && pathLenSub > ptInfos[ysub][xsub][4]) {//可以滑并且可以得到更多的步數(shù),則更新
                ptInfos[ysub][xsub][2= y;
                ptInfos[ysub][xsub][
3= x;
                ptInfos[ysub][xsub][
4= pathLenSub;
                updateSubPathLen(ysub, xsub);
            }

        }

    }


///以下為測試代碼    
//////////////////////////////////////////////////////////////////////////////////////////////
    
    
public static void main(String[] args) {
//        {
//            int[][] pts = {
//                    {1,  2,  3,  4,  5},
//                    {16, 17, 18, 19, 6},
//                    {15, 24, 25, 20, 7},
//                    {14, 23, 22, 21, 8},
//                    {13, 12, 11, 10, 9}
//            };
//            Skee2 skee = new Skee2(pts);
//            skee.computePath();
//            skee.printMaxStep();
//            System.out.println("最長步數(shù)為:" +skee.getMatStep());
//        }
        
        
        
{
            
int yw = 100, xw = 100;
            
boolean isPrintMatrix = false;
            
int[][] pts = new int[yw][xw];
            createLuoXuanMatrix(pts, 
-1, xw, -1, yw, 0000);

            
if (isPrintMatrix) {
                System.out.println(
"螺旋矩陣:");
                
int formatLen = Integer.toString(yw * yw -1).length();
                
for (int y = 0; y < yw; y++{
                    
for (int x = 0; x < xw; x++{
                        System.out.print(getNSpace(formatLen
-Integer.toString(pts[y][x]).length()) + pts[y][x] + " ");
                    }

                    System.out.println();
                }

                System.out.println(
"----- End Matrix -----\n");
            }

            
            
long time = System.currentTimeMillis();
            
            Skee skee 
= new Skee(pts);
            skee.computePath();
            
//skee.printMaxStep();
            System.out.println("最長步數(shù)為:" +skee.getMatStep());
            
            System.out.println();
            System.out.println(
"總時間:" + (System.currentTimeMillis() - time));
        }

    }

    
    
    
    
///創(chuàng)建螺旋矩陣
    
//用于產(chǎn)生螺旋數(shù)矩陣
    public static void createLuoXuanMatrix(int[][] pts, int xMin, int xMax, int yMin, int yMax, int dir, int now, int x, int y) {
        
switch (dir) {
            
case 0://向右
                if (xMin >= xMax) {
                    
return;
                }

                
while (x < xMax) {
                    pts[y][x
++= now++;
                }

                x
--;
                now
--;
                yMin
++;
                
break;
            
case 1://向下
                if (yMin >= yMax) {
                    
return;
                }

                
while (y < yMax) {
                    pts[y
++][x] = now++;
                }

                y
--;
                now
--;
                xMax
--;
                
break;
            
case 2://向左
                if (xMin >= xMax) {
                    
return;
                }

                
while (x > xMin) {
                    pts[y][x
--= now++;
                }

                x
++;
                now
--;
                yMax
--;
                
break;
            
case 3://向上
                if (yMin >= yMax) {
                    
return;
                }

                
while (y > yMin) {
                    pts[y
--][x] = now++;
                }

                y
++;
                now
--;
                xMin
++;
                
break;
            
default:
                
break;
        }

        dir 
= (dir + 1% 4;
        createLuoXuanMatrix(pts, xMin, xMax, yMin, yMax, dir, now, x, y);
    }

    
public static String getNSpace(int count) {
        
return "          ".substring(0, count);
    }

}