对于该题目直接用DFS或者BFS都可以直接暴力出来,实际上题目也不难,只需要递归一个搜索方法即可。那么用C或者C++将很容易的解决这个题目。
但是如果用JAVA写的话将存在一个昨晚让我纠结了很久的问题:输入信息需要以字符数组的形式存储,那么如何解决标记以及存储的问题?
刚开始我定义了一个二维字符数组,并且输入用了整形输入,然后通过强制转换的方法将存储转化为字符型。但是实际上在运行的过程中就出现了输入类型与定义类型不符的问题。代码如下:
import java.util.Scanner; public class RedAndBlack { static Scanner input = new Scanner(System.in); static char[][] Room = new char[20][20]; public static void main(String[] args){ while (true){ //初始化矩阵的列与行 int y=input.nextInt(); int x=input.nextInt(); //如果行列均为0,结束程序 if (x==0&&y==0) break; //初始化地板信息 for (int i=0;i<x;i++){ for (int j=0;j<y;j++){ Room[i][j]=(char)input.nextInt(); } System.out.println(); } //记录所有可以行走的地板 for (int i=0;i<x;i++){ for (int j=0;j<y;j++){ if (Room[i][j]=='@') System.out.println(calcu(i,j,x,y)); } } } } static int calcu(int a,int b,int h,int l){ if (a<0||a>=h||b<0||b>=l) return 0; else if (Room[a][b]=='#') return 0; else{ Room[a][b]='#'; return 1+calcu((a+1),b,h,l)+calcu(a,(b+1),h,l)+calcu((a-1),b,h,l)+calcu(a,(b-1),h,l); } } }
显然这样并不能解决字符类型的数组输入。所以我开始改用定义一个一维字符串数组,但是一样存在一个问题:
当一块地板已经被这个人踩了以后,即已经记录在数目里面,如果将这块地板改为不能再踩,即如何标记出这块地板已经被计算过。如果用类C语言将很容易解决这个问题,因为类C语言可以直接进行字符数组或者用字符串下脚标所以来进行数据更换。
显然,在JAVA中没有对于一个字符串仅仅改掉其中某一个字符的方法的前提下,要想标记出一块地板已经被记录,只好再声明一个二维整形数组在初始化以后将已经被记录的地板进行标记,最后再额外在搜索函数中增加一个判断是否记录过的方法即可。
代码如下:
import java.util.Scanner; import java.lang.String; public class RedAndBlack { static Scanner input = new Scanner(System.in); static String[] Room = new String[20]; static int[][] judge=new int[20][20]; static int m,n; public static void main(String[] args){ while (true){ //初始化矩阵的列与行 n=input.nextInt(); m=input.nextInt(); //如果行列均为0,结束程序 if (n==0&&m==0) break; for (int i=0;i<m;i++){ for (int j=0;j<n;j++){ judge[i][j]=0; } } //初始化地板信息 for (int i=0;i<m;i++){ // System.out.println("hello"); //for (int j=0;j<y;j++){ // System.out.println(); Room[i]=input.next(); //} // System.out.println(); } //记录所有可以行走的地板 for (int i=0;i<m;i++){ for (int j=0;j<n;j++){ if (Room[i].charAt(j)=='@') System.out.println(calcu(i,j)); } } } } static int calcu(int a,int b){ if (a<0||a>=m||b<0||b>=n) return 0; if (Room[a].charAt(b)=='#') return 0; if (judge[a][b]==1) //标记数组0表示标记, 1表示记录过 return 0; //所有满足没有标记过的地板,先标记为1然后再递归。 judge[a][b]=1; return 1+calcu((a+1),b)+calcu(a,(b+1))+calcu((a-1),b)+calcu(a,(b-1)); } }