上次贴的代码不对,这次更新了一下
下载
/** *//**
滑雪Description
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 27578 Accepted: 9545
Michael喜欢滑雪百这并不奇怪, 因为滑雪的确很刺激。可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你。
Michael想知道载一个区域中最长底滑坡。区域由一个二维数组给出。数组的每个数字代表点的高度。下面是一个例子
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
一个人可以从某个点滑向上下左右相邻四个点之一,当且仅当高度减小。在上面的例子中,一条可滑行的滑坡为24-17-16-1。当然25-24-23--3-2-1更长。事实上,这是最长的一条。
Input
输入的第一行表示区域的行数R和列数C(1 <= R,C <= 100)。下面是R行,每行有C个整数,代表高度h,0<=h<=10000。
Output
输出最长区域的长度。
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
*/
/** *//**
* 得考虑到有相同高度的点,所以中途应该记录坐标
* 最高点与最低点可以有多个,但是假设:终点只有一个,就是第一个最低的点。出发点只有一个,第一个最高的点。
*/
public class Skee {
public int xw,yw;//矩阵的长与宽
//前两维索引是点坐标,最后一维:
//[0]当前点的高度 [1]是否(1|0)曾到达过该点 [2,3]当前最佳上一点坐标y,x [4]当前到该步为止最佳路径长度
//[5,6][7,8][9,10][11,12]分别为上下左右下一步的点的坐标,若为(-1,-1)则该点对应方向不可以走,或者该点还未向四周滑动
public int[][][] ptInfos;//[y][x][13]
//[0] 高度 [1]是1否0己有父坐标 [2,3]当前最远路径父坐标y,x [4]路径长度 [5,6][7,8][9,10][11,12]分别为上下左右下一步坐标
//存储当前轮可以滑动的点以及下一轮可以滑动的点
//[点数][3] 第二维的三分别为:Index0值:0该点未使用或己作废,1本轮可向四周滑动的点,2本轮新加入的点_下一轮才能向四周滑动 (Index1,Index2)点坐标
public int[][] ptNowStep;
int ptNowStepTop = 0;//当前使用到的位置的顶部,可以理解为栈顶的意思吧
int ptNowStepIndex;//一个可以利用的存新的未走过的点的位置
int ptNowStepRecycle = -1;//最后一个回收的点
int Point_StartX, Point_StartY, Point_EndX, Point_EndY;//出发点与终点的坐标
int xNow, yNow, xNext, yNext, hNow;//当前点的坐标、下一步的坐标、当前点的高度
boolean canNextStep;//己加入新的未走过的点,需要继续滑
public int[] hightPath;
//pts矩阵,存储各坐标点对应的高度
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;
}
}
}
//找到出发点与终点
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;
}
}
}
//初始化出发点
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());
}
//返回最长步数(实际是点数)
public int getMatStep() {
return ptInfos[Point_EndY][Point_EndX][4];
}
//打印出最长步数的所有点高度
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]) {//可以得到更多的步数,则更新
//下一步的父指向更新
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;
}
}
}
//更新后继步的步数
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]) {//可以滑并且可以得到更多的步数,则更新
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("最长步数为:" +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("最长步数为:" +skee.getMatStep());
System.out.println();
System.out.println("总时间:" + (System.currentTimeMillis() - time));
}
}
///创建螺旋矩阵
//用于产生螺旋数矩阵
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 |
|
导航
统计
- 随笔: 115
- 文章: 1
- 评论: 86
- 引用: 0
常用链接
留言簿(5)
随笔档案(115)
网址
搜索
积分与排名
最新评论
阅读排行榜
评论排行榜
|
|