OpenJ_Bailian - 1088
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
这个题改了很多遍,很多地方理解的不到位,特别的对DFS,(以前也碰到了很多),因为太久不练,所以遇到了很多问题:
1.DFS和BFS一定要区分使用环境,注意到BFS的vis是公用的
2.DFS的vis在true之后要改为false,注意!不能够将修改后的vis作为参数传递出去,因为传出去的VIS(数组)(应该)是个地址,在新的DFS中修改VIS后,就把所有的vis都修改了,达不到不改变本体的效果!
3.记忆化搜索,注意DFS的定义,和DP的定义
dp[i][j]就是对点i,j的最远滑行路径,但凡不为0,就一定是成立的,完全的。
dfs(i,j),输出的就是dp[i][j],仅仅是当dp[i][j]不知道时,我们才会采用的策略。
DFS输出的永远是dp[i][j]
AC代码:(因为天生有访问顺序,arr[i][j]>arr[ti][tj],所以不用考虑vis数组,不用担心重复回访)
import java.util.Scanner;
public class Main{
static int arr[][];
static int[][] dir = {{1,0},{-1,0},{0,1},{0,-1}};
static int x,y;
static int dp[][];
// static boolean vis[][];
public static void main(String args[]){
Scanner sc = new Scanner(System.in);
x = sc.nextInt();
y = sc.nextInt();
arr = new int[x][y];
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {
arr[i][j] = sc.nextInt();
}
}
dp = new int[x][y];
int max = -1;
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {
max = Math.max(max, dfs(i,j));
}
}
System.out.println(max);
}
private static int dfs(int i, int j) {
if(dp[i][j]!=0) return dp[i][j];
int ans = 0;
for (int p = 0; p < dir.length; p++) {
int xx = i+dir[p][0];
int yy = j+dir[p][1];
if(xx>=0&&yy>=0&&xx
超时代码:DFS+剪枝(迷)
import java.util.Scanner;
public class Main{
static int arr[][];
static int[][] dir = {{1,0},{-1,0},{0,1},{0,-1}};
static int x,y;
static int dp[][];
static boolean vis[][];
public static void main(String args[]){
Scanner sc = new Scanner(System.in);
x = sc.nextInt();
y = sc.nextInt();
arr = new int[x][y];
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {
arr[i][j] = sc.nextInt();
}
}
vis = new boolean[x][y];
dp = new int[x][y];
for (int i = 0; i < dp.length; i++) {
for (int j = 0; j < dp[i].length; j++) {
dp[i][j] = 1;
}
}
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {
vis[i][j]=true;
dfs(i,j,1);
vis[i][j]=false;
}
}
int max = -1;
for (int i = 0; i < dp.length; i++) {
for (int j = 0; j < dp[i].length; j++) {
if(max=0&&yy>=0&&xxarr[i][j]) {
vis[xx][yy]=true;
dfs(xx,yy,k+1);
vis[xx][yy]=false;
}
}
}
dp[i][j] = Math.max(dp[i][j], k);
return k;
}
}
最初的愚蠢(大量重复无效工作)代码:(纯DFS、超时)
import java.util.Scanner;
public class Main{
static int arr[][];
static int ans = -1;
static int[][] dir = {{1,0},{-1,0},{0,1},{0,-1}};
static int x,y;
public static void main(String args[]){
Scanner sc = new Scanner(System.in);
x = sc.nextInt();
y = sc.nextInt();
arr = new int[x][y];
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {
arr[i][j] = sc.nextInt();
}
}
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {
boolean vis[][] = new boolean[x][y];
vis[i][j] = true;
dfs(i,j,1,vis);
vis=null; //清空数组,节省内存
//不能BFS,因为公用一个VIS
// q.clear();
// q.add(new Node(2,2,1));
// while(!q.isEmpty()) {
// temp = q.poll();
// vis[temp.x][temp.y] = true;
// if(temp.l>ans) ans= temp.l;
// for (int k = 0; k < dir.length; k++) {
//// System.out.println(temp.x+" "+temp.y+" "+dir[k][0]+" "+dir[k][1]);
// xx = temp.x+dir[k][0];
// yy = temp.y+dir[k][1];
// if(xx>=0 && xx=0 && yyans) ans= k;
for (int p = 0; p < dir.length; p++) {
int xx = i+dir[p][0]; //new int!
int yy = j+dir[p][1];
if(xx>=0 && xx=0 && yy