Problem
Due to recent rains, water has pooled in various places in Farmer John’s field, which is represented by a rectangle of N x M (1 <= N <= 100; 1 <= M <= 100) squares. Each square contains either water (‘W’) or dry land (’.’). Farmer John would like to figure out how many ponds have formed in his field. A pond is a connected set of squares with water in them, where a square is considered adjacent to all eight of its neighbors. Given a diagram of Farmer John’s field, determine how many ponds he has.
由于近期的降雨,雨水汇集在农民约翰的田地不同的地方。我们用一个NxM(1<=N<=100;1<=M<=100)网格图表示。每个网格中有水(‘W’) 或是旱地(’.’)。一个网格与其周围的八个网格相连,而一组相连的网格视为一个水坑。约翰想弄清楚他的田地已经形成了多少水坑。给出约翰田地的示意图,确定当中有多少水坑。
Line 1: Two space-separated integers: N and M * Lines 2…N+1: M characters per line representing one row of Farmer John’s field. Each character is either ‘W’ or ‘.’. The characters do not have spaces between them.
第1行:两个空格隔开的整数:N 和 M 第2行到第N+1行:每行M个字符,每个字符是’W’或’.’,它们表示网格图中的一排。字符之间没有空格。
Output
Line 1: The number of ponds in Farmer John’s field.
一行:水坑的数量
BFS (Using Stack)
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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 import java.util.Scanner;public class Main { public static void main (String[] args) { Scanner input = new Scanner(System.in); int n = input.nextInt(); int m = input.nextInt(); input.nextLine(); String[][] field = new String[n+1 ][m+1 ]; for (int i=0 ;i<n;i++) { String a = input.nextLine(); for (int j=0 ;j<m;j++) { String s = String.valueOf(a.charAt(j)); field[i][j]= s; } } input.close(); int pool =0 ; int [][] mark = new int [n+1 ][m+1 ]; Stack route = new Stack(); for (int i =0 ;i<n;i++) { for (int j= 0 ;j<m;j++) { if (mark[i][j]==0 && field[i][j].equals("W" )==true ) { int [] start ={i,j}; mark[i][j]=1 ; route.push(start); pool++; while (route.is_empty()==false ) { start = route.pop(); move(route,field,start,m,n,mark); } } else { mark[i][j]=1 ; } } } System.out.println(pool); } public static void move (Stack stack,String[][] field, int [] a, int m, int n ,int [][] mark) { int x = a[0 ]; int y = a[1 ]; int [] moveX = {1 ,1 ,1 ,0 ,0 ,-1 ,-1 ,-1 }; int [] moveY = {0 ,1 ,-1 ,1 ,-1 ,0 ,1 ,-1 }; String j = "W" ; for (int i=0 ;i<8 ;i++) { if (x+moveX[i]>=0 && x+moveX[i]<n && y+moveY[i]>=0 && y+moveY[i]<m && mark[x+moveX[i]][y+moveY[i]]==0 && j.equals(field[x+moveX[i]][y+moveY[i]])) { int [] next = {x+moveX[i],y+moveY[i]}; stack.push(next); mark[next[0 ]][next[1 ]]=1 ; } } } public static class Stack { public final int INITIAL_STACK_SIZE = 1000 ; public int [][] base; public int top; public Stack () { base = new int [10000 ][2 ]; top = 0 ; } public void push (int [] a) { base[top++] = a; } public int [] get_top() { return base[top-1 ]; } public int [] pop(){ top--; return base[top]; } public boolean is_empty () { if (top==0 ) { return true ; } else { return false ; } } } }
Waterpool1: Scanner 输入的问题
next() 方法在读取内容时,会过滤掉有效字符前面的无效字符,对输入有效字符之前遇到的空格键、Tab键或Enter键等结束符,next()方法会自动将其过滤掉;只有在读取到有效字符之后,next()方法才将其后的空格键、Tab键或Enter键等视为结束符;所以next()方法不能得到带空格的字符串.
nextLine() 方法返回的是Enter键之前没有被读取的所有字符,是可以得到带空格的字符串的.
next()方法读取到空白符结束,nextLine()读取到回车结束(“\r”).
Quote: java的nextLine()的一个报错引发的思考
Solution: 在nextInt读入两数字后再加nextLine()读取换行符,不做处理。之后就可以顺利读入地形图了.
Waterpool2: 将field按单个字符以字符串的形式输入需要先讲nextLine读入的整行解析为char,再转为字符串
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 1. String s = String.valueOf('c' ); 2. String s = String.valueOf(new char []{'c' }); 3. String s = Character.toString('c' );4. String s = new Character('c' ).toString();5. String s = "" + 'c' ;6. String s = new String(new char []{'c' });
Quote: Java中char和String的转换
Waterpool3&Waterpool4: 判定两字符串相等使用a.equals(b)
,且调用时需保证a为常量b为变量,不然会报java.lang.NullPointerException .
在Java中由于字符串是对象类型,所以不能简单的用“==” 判断两个字符串是否相等,而使用 equals()方法比较两个对象的内容.
注意: equals()方法比较的是对象的内容(区分字母的大小写格式) ,但是如果使用“==”操作符比较两个对象时, 比较的是两个对象的内存地址, 所以它们不相等 (即使内容相同, 不同对象的内存地址也是不相同的)
Quote: java 判断两个字符串相等
变量.equals(常量)且变量为null时,变成了null.equals(“常量”),而null不属于String类型,所以无法调用String.class里面的equals方法,而常量.equals(变量)时,常量最少也是 “” ,属于String类型,所以可以调用它下面的方法.
Quote: String.equals报java.lang.NullPointerException
Waterpool5: Stack初始化时内存大小
Stack中存储相连的“W”位置(位置信息为int[]),因此初始化Stack为二维数组,base[i][j]中j取值为0,1两种可能,而i的最大极端情况为100*100均为水坑,因此应为10000.
Hint1: 向八个方向搜索时不用写8个if,将8个方位的xy坐标变化值对应存入数组使用for循环即可模拟~
DFS (Using Recursion)
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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 import java.util.Scanner;public class fieldDfs { public static String[][] field = new String[1000 ][1000 ]; public static int [][] vis = new int [1000 ][1000 ]; public static void main (String[] args) { Scanner input = new Scanner(System.in); int n = input.nextInt(); int m = input.nextInt(); input.nextLine(); for (int i=0 ;i<n;i++) { String a = input.nextLine(); for (int j=0 ;j<m;j++) { String s = String.valueOf(a.charAt(j)); field[i][j]= s; } } input.close(); int ans = 0 ; for (int i=0 ;i<n;i++) { for (int j=0 ;j<m;j++) { if ("W" .equals(field[i][j]) && vis[i][j]==0 ) { ans++; dfs(n,m,i,j); } } } System.out.println(ans); } public static int [] moveX = {1 ,1 ,1 ,0 ,0 ,-1 ,-1 ,-1 }; public static int [] moveY = {0 ,1 ,-1 ,1 ,-1 ,0 ,1 ,-1 }; public static void dfs (int n,int m,int x, int y) { vis[x][y]=1 ; for (int i=0 ;i<=7 ;i++) { int new_x = x+moveX[i]; int new_y = y+moveY[i]; if (new_x>=0 && new_x<n && new_y>=0 && new_y<m &&"W" .equals(field[new_x][new_y]) && vis[new_x][new_y]==0 ){ dfs(n,m,new_x,new_y); } } } }