poj1088滑雪

来源:互联网 发布:java实现群发短信 编辑:程序博客网 时间:2024/05/22 00:05

刚接触Java编程不久,只会一些基本语法,在算法方面基本小白,所以今天做到了这个题目还是很开心的。

首先拿到这个题目的时候有点尴尬,不知道怎么办,大神不要笑话。。。没有具体的实现思路,只是知道模糊的轮廓,于是转而求助大神,于是知道这原来属于动态规划的问题,并且了解了新名词:记忆化搜索。

具体记忆化搜索是什么概念,我就不具体说了,说不清楚,不官方也不全面,这里直接附上链接:http://blog.csdn.net/urecvbnkuhbh_54245df/article/details/5847876

这里放在1088里来寻找最长路径,因为在这道题里采用了迭代的算法,也就是说在求一个点到最低点的路径长度的问题上,可能要通过它周围的点的路径长度来求得,而周围的那个点的路径长度可能也要通过它本身的周围的点的路径长度,如此反复,因为要遍历到数组中的每个点,所以在遍历和迭代的过程肯定会有点重复被用到,这个时候用一个点再去求一次肯定是不现实的,因为时间复杂度会过于庞大,因此用到记忆化搜索,就是说我求出一个点的路径长度,就把他记录下次,等下一次遍历或者迭代时有用到这个点,就可以直接得到他的路径长度。

想通了这些之后,实现起来并不麻烦,代码如下:

package cn.itcast_test;


import java.util.Scanner;


public class Poj1088 {
private static int height[][];
private static int memory[][];
private static int n;
private static int m;

public static void main(String args[]){
Scanner scan=new Scanner(System.in);
n=scan.nextInt();
m=scan.nextInt();

height=new int[n+2][m+2];
memory=new int[n+2][m+2];
int biggest=0;   //用来存储当前已找到的最长路径

for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
height[i][j]=scan.nextInt();
}
}   //数组存储每一个点的高度高度

for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
memory[i][j]=deep(i,j);
if(memory[i][j]>biggest){
biggest=memory[i][j];
}
}
}

System.out.println(biggest);
}

public static int deep(int i,int j){     //利用递归的方法求某个点的最长路径
int max=0;         //用来记录该点的最长路径
int temp=0;

if(i<1||j<1||i>n||j>m){
return 0;
}    //超出了数组搜索范围则返回0

if(memory[i][j]!=0){
return memory[i][j];
}

if(height[i][j]>height[i][j+1]){
temp=deep(i,j+1);
if(temp>max)
max=temp;
}

if(height[i][j]>height[i][j-1]){
temp=deep(i,j-1);
if(temp>max)
max=temp;
}

if(height[i][j]>height[i-1][j]){
temp=deep(i-1,j);
if(temp>max)
max=temp;
}

if(height[i][j]>height[i+1][j]){
temp=deep(i+1,j);
if(temp>max)
max=temp;
}

return max+1;
}


}


更新:在学习动态规划的时候又重新做了一下这道题,觉得上面代码有一个地方需要改进一下会比较好,

if(height[x][y]>height[x-1][y]) {temp=deep(x-1,y);if(temp>=max)max=temp+1;}


在这个地方,我觉得temp应该大于等于max,在之前的代码中是直接temp>max,因为假设temp和max相等,但同时,max对应位置的高度是比temp对应位置的高度高的,所以可以从max位置下滑到temp位置,由此max与temp相等应该也是可以的。

对于下面的几个情况也是一样的分析喽。