动态规划最大的特点就是用空间换时间。
比如:同一道题用dfs可能只有90分,因为有测试用例会超时;而用动态规划就能很好的解决这一问题,因为动态规划是有记忆的dfs,这样就能省去很多不必要的重复搜索!
以下面这道题为例:
DFS代码如下:
/**
* 从(i,j)位置开始搜索(往下滑雪)
* @param a
* @param i
* @param j
*/
private static void dfs(int[][] a, int i, int j, int steps) {
if ( i < 0 || i >= R || j < 0 || j >= C ) {
return;
}
ans = Math.max(ans, steps);
//up
if ( i-1 >= 0 && a[i-1][j] < a[i][j]) {
dfs(a, i-1, j, steps+1);
}
//down
if ( i+1 < R && a[i+1][j] < a[i][j]) {
dfs(a, i+1, j, steps+1);
}
//left
if ( j-1 >= 0 && a[i][j-1] < a[i][j]) {
dfs(a, i, j-1, steps+1);
}
//right
if ( j+1 < C && a[i][j+1] < a[i][j]) {
dfs(a, i, j+1, steps+1);
}
// System.out.println(steps);
}
这样只能通过部分用例~~~
所谓动态规划就是在DFS得基础上进行记忆化搜索,那么问题来到了如何进行记忆化搜索:很简单,创建一个和原数组一样规模得数组,在这个数组得每个位置记录当前位置上得最优解,这样在后面某个位置搜索到这个位置时就不用继续搜索下去,因为之前已经记录了这个位置得最优解,直接返回即可!最后找到最大步数即可~~~
动态规划核心代码如下:
/**
* 在记忆化搜索的过程中更新(x,y)处的值
* @param x
* @param y
* @return
*/
private static int dfs(int x, int y) {
if (val[x][y]!=0) {
return val[x][y];
}
val[x][y] = 1;
//搜索四个方向
for (int i = 0; i < 4; i++) {
int xx = x+dx[i];
int yy = y+dy[i];
if ( xx >= 0 && yy >= 0 && xx < R && yy < C && a[x][y] > a[xx][yy]) {
dfs(xx, yy);
val[x][y] = Math.max(val[x][y], val[xx][yy]+1);
}
}
return val[x][y];
}
全部代码如下:
package lqbTest;
import java.util.Scanner;
/*
* 滑雪DP
*/
public class huaXueDP {
private static int R;
private static int C;
private static int[][] a;
private static int[][] val;
private static int ans;
private static int[] dx = {0,0,1,-1};
private static int[] dy = {1,-1,0,0};
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner scanner = new Scanner(System.in);
R = scanner.nextInt();
C = scanner.nextInt();
a = new int[R][C];
for (int i = 0; i < R; i++) {
for (int j = 0; j < C; j++) {
a[i][j] = scanner.nextInt();
}
}
//开始记忆化搜索
val = new int[R][C];
for (int i = 0; i < R; i++) {
for (int j = 0; j < C; j++) {
ans = Math.max(ans, dfs(i, j));
if (ans == R*C) {
break;
}
}
}
System.out.println(ans);
}
/**
* 在记忆化搜索的过程中更新(x,y)处的值
* @param x
* @param y
* @return
*/
private static int dfs(int x, int y) {
if (val[x][y]!=0) {
return val[x][y];
}
val[x][y] = 1;
//搜索四个方向
for (int i = 0; i < 4; i++) {
int xx = x+dx[i];
int yy = y+dy[i];
if ( xx >= 0 && yy >= 0 && xx < R && yy < C && a[x][y] > a[xx][yy]) {
dfs(xx, yy);
val[x][y] = Math.max(val[x][y], val[xx][yy]+1);
}
}
return val[x][y];
}
}
提交结果全部AC