上次貼的代碼不對,這次更新了一下
下載
 /** *//**
滑雪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, 0, 0, 0, 0);

 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);
}
}
|
|
|
| 日 | 一 | 二 | 三 | 四 | 五 | 六 |
---|
31 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
|
導(dǎo)航
統(tǒng)計
- 隨筆: 115
- 文章: 1
- 評論: 86
- 引用: 0
常用鏈接
留言簿(5)
隨筆檔案(115)
網(wǎng)址
搜索
積分與排名
最新評論

閱讀排行榜
評論排行榜
|
|