Description
Michael喜欢滑雪百这并不奇怪, 因为滑雪的确很刺激。可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你。Michael想知道载一个区域中最长底滑坡。区域由一个二维数组给出。数组的每个数字代表点的高度。下面是一个例子
一个人可以从某个点滑向上下左右相邻四个点之一,当且仅当高度减小。在上面的例子中,一条可滑行的滑坡为24-17-16-1。当然25-24-23-...-3-2-1更长。事实上,这是最长的一条。
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
Source
SHTSC 2002
思路:
首先观察到可滑行的滑坡是一个序列X1,X2,X3,X4...Xn。 由于可滑行的条件是严格递减,那么:- 序列中没有重复的数字;
- 不可能出现环路。
C/C++
本代码来自http://www.cppblog.com/abilitytao/archive/2010/11/25/74271.html
//============================================================================
// Name : Poj1088.cpp
// Author :
// Version :
// Copyright : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================
#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
struct dot {
int x;
int y;
int h;
};//创建一个结构体存储每个点的信息
dot line[20000]; //将每个点存入该结构体数组
int height[120][120]; //用于存储input
int len[120][120]; //dp数组,存储每个点的最优解
int cmp(const void *a, const void *b) {
if ((*(dot *) a).h > (*(dot *) b).h)
return 1;
else
return -1;
}//快速排序的参考函数
int main() {
int m, n;
int i, j;
int flag = -1;
int max = 0;
cin >> m >> n;
for (i = 1; i <= m; i++) {
for (j = 1; j <= n; j++) {
flag++;
scanf("%d", &height[i][j]);
line[flag].x = i;
line[flag].y = j;
line[flag].h = height[i][j];
}
} //这个双层循环用来完成数据收集的工作
qsort(line, m * n, sizeof(line[0]), cmp); //对结构体的h参数进行排序
for (i = 0; i < m * n; i++) {
if (height[line[i].x][line[i].y] < height[line[i].x][line[i].y + 1]
&& len[line[i].x][line[i].y] >= len[line[i].x][line[i].y + 1]) {
len[line[i].x][line[i].y + 1] = len[line[i].x][line[i].y] + 1;
}
if (height[line[i].x][line[i].y] < height[line[i].x + 1][line[i].y]
&& len[line[i].x][line[i].y] >= len[line[i].x + 1][line[i].y]) {
len[line[i].x + 1][line[i].y] = len[line[i].x][line[i].y] + 1;
}
if (height[line[i].x][line[i].y] < height[line[i].x][line[i].y - 1]
&& len[line[i].x][line[i].y] >= len[line[i].x][line[i].y - 1]) {
len[line[i].x][line[i].y - 1] = len[line[i].x][line[i].y] + 1;
}
if (height[line[i].x][line[i].y] < height[line[i].x - 1][line[i].y]
&& len[line[i].x][line[i].y] >= len[line[i].x - 1][line[i].y]) {
len[line[i].x - 1][line[i].y] = len[line[i].x][line[i].y] + 1;
}
} //动态规划过程
for (i = 1; i <= m; i++) {
for (j = 1; j <= n; j++) {
if (len[i][j] > max)
max = len[i][j];
}
} //遍历len数组,求出最大值
cout << max + 1 << endl;// 因为初始值是0,所以最后要加一
return 0;
}
Java
import java.util.Arrays;
import java.util.Comparator;
import java.util.Scanner;
public class Skier {
public static void main(String[] args) {
int[][] mat;
int[][] serlen;
int row, column;
Scanner sin = new Scanner(System.in);
row = sin.nextInt();
column = sin.nextInt();
mat = new int[row + 2][column + 2];
serlen = new int[row + 2][column + 2];
Dot[] dots = new Dot[row * column];
int cur = 0;
for (int i = 0; i < row + 2; i++) {
for (int j = 0; j < column + 2; j++) {
serlen[i][j] = 0;
mat[i][j] = Integer.MAX_VALUE;
}
}
for (int i = 1; i <= row; i++) {
for (int j = 1; j <= column; j++) {
int tmp = sin.nextInt();
mat[i][j] = tmp;
dots[cur] = new Dot(i, j, tmp);
cur++;
}
}
Arrays.sort(dots, new Dotcompare());
int[][] direction = { { 0, 1 }, { 1, 0 }, { 0, -1 }, { -1, 0 } };
for (Dot d : dots) {
int max = 0;
for (int i = 0; i < 4; i++) {
int itmp = d.i + direction[i][0];
int jtmp = d.j + direction[i][1];
if (d.value > mat[itmp][jtmp]) {
if (serlen[itmp][jtmp] > max) {
max = serlen[itmp][jtmp];
}
}
}
serlen[d.i][d.j] = max + 1;
}
int result = 0;
for (int i = 1; i <= row; i++) {
for (int j = 1; j <= column; j++) {
if (serlen[i][j] > result) {
result = serlen[i][j];
}
}
}
System.out.println("The result is " + result);
}
}
class Dot {
int i;
int j;
int value;
public Dot(int i, int j, int value) {
this.i = i;
this.j = j;
this.value = value;
}
}
class Dotcompare implements Comparator<Dot> {
@Override
public int compare(Dot o1, Dot o2) {
if (o1.value > o2.value) {
return 1;
} else if (o1.value < o2.value) {
return -1;
} else {
return 0;
}
}
}
Java(DP without sorting)
import java.util.Scanner;
public class Skier2 {
public static void main(String[] args) {
int[][] mat;
int[][] serlen;
int row, column;
Scanner sin = new Scanner(System.in);
row = sin.nextInt();
column = sin.nextInt();
mat = new int[row + 2][column + 2];
serlen = new int[row + 2][column + 2];
for (int i = 0; i < row + 2; i++) {
for (int j = 0; j < column + 2; j++) {
serlen[i][j] = 0;
mat[i][j] = Integer.MAX_VALUE;
}
}
for (int i = 1; i <= row; i++) {
for (int j = 1; j <= column; j++) {
int tmp = sin.nextInt();
mat[i][j] = tmp;
}
}
for (int i = 1; i <= row; i++) {
for (int j = 1; j <= column; j++) {
f(mat, serlen, i, j);
}
}
int result = 0;
for (int i = 1; i <= row; i++) {
for (int j = 1; j <= column; j++) {
if (serlen[i][j] > result) {
result = serlen[i][j];
}
}
}
System.out.println("The result is " + result);
}
private static void f(int[][] mat, int[][] serlen, int i, int j) {
if(serlen[i][j] != 0){
return ;
}
int[][] direction = { { 0, 1 }, { 1, 0 }, { 0, -1 }, { -1, 0 } };
boolean has = false;
int max = 0;
for(int k = 0; k < 4; k++){
int itmp = i + direction[k][0];
int jtmp = j + direction[k][1];
if (mat[i][j] > mat[itmp][jtmp]) {
has = true;
f(mat, serlen, itmp, jtmp);
if(max < serlen[itmp][jtmp]){
max = serlen[itmp][jtmp];
}
}
}
serlen[i][j] = max + 1;
if(!has){
serlen[i][j] = 1;
}
}
}