目录
一、红与黑
(1)原题再现
有一间长方形的房子,地上铺了红色、黑色两种颜色的正方形瓷砖。你站在其中一块黑色的瓷砖上,只能向相邻的(上下左右四个方向)黑色瓷砖移动。请写一个程序,计算你总共能够到达多少块黑色的瓷砖。
输入描述:
输入包含多组数据。 每组数据第一行是两个整数 m 和 n(1≤m, n≤20)。紧接着 m 行,每行包括 n 个字符。每个字符表示一块瓷砖的颜色,规则如下: 1. “.”:黑色的瓷砖; 2. “#”:白色的瓷砖; 3. “@”:黑色的瓷砖,并且你站在这块瓷砖上。该字符在每个数据集合中唯一出现一次。
输出描述:
对应每组数据,输出总共能够到达多少块黑色的瓷砖。
示例1
输入
9 6
....#.
.....#
......
......
......
......
......
#@...#
.#..#.
输出
45
(2)问题分析
用深度优先遍历去做。找到开始的位置,然后开始遍历找到所有的黑瓷砖,注意记录瓷砖数量的count要为静态全局变量,不然每一次回溯就又变回去了。
(3)完整代码
import java.util.Scanner; /* * 红与黑 */ public class Main { static int count=1;//黑砖数量,初始为1 public static void main(String[] args) { Scanner sc=new Scanner(System.in); while(sc.hasNext()) { int row=sc.nextInt(); int col=sc.nextInt(); sc.nextLine();//吸收数字之后的回车 char [][] loc=new char[row][col]; for (int i = 0; i < row ; i++) { String str=sc.nextLine(); for (int j = 0; j < col; j++) { loc[i][j]=str.charAt(j); } } int x=0;int y=0;//初始位置 int f=0;//判断是否跳出外层循环 for (int i = 0; i < row ; i++) { for (int j = 0; j < col; j++) { if(loc[i][j]=='@') { x=i; y=j; f=1; break; } } if(f==1) { break; } } int flag[][]=new int [row][col];//标记是否走过 int [][]location= {{1,0},{-1,0},{0,1},{0,-1}};//四个方位 count=1; dfs(loc, flag, location, x, y, row, col); System.out.println(count); } System.out.println(); } public static void dfs(char [][]loc,int [][]flag,int[][] location,int x,int y,int row,int col) { for(int i=0;i<4;i++) { int newX=x+location[i][0]; int newY=y+location[i][1]; if(newX<0||newX>=row||newY<0||newY>=col) { continue; } if(loc[newX][newY]=='.'&&flag[newX][newY]==0) {//是黑瓷砖且没有标记过 ++count; flag[newX][newY]=1; dfs(loc, flag, location, newX, newY, row, col); } } } }
二、蘑菇阵
(1)原题再现
现在有两个好友A和B,住在一片长有蘑菇的由n*m个方格组成的草地,A在(1,1),B在(n,m)。现在A想要拜访B,由于她只想去B的家,所以每次她只会走(i,j+1)或(i+1,j)这样的路线,在草地上有k个蘑菇种在格子里(多个蘑菇可能在同一方格),问:A如果每一步随机选择的话(若她在边界上,则只有一种选择),那么她不碰到蘑菇走到B的家的概率是多少?
输入描述:
第一行N,M,K(1 ≤ N,M ≤ 20, k ≤ 100),N,M为草地大小,接下来K行,每行两个整数x,y,代表(x,y)处有一个蘑菇。
输出描述:
输出一行,代表所求概率(保留到2位小数)
示例1
输入
2 2 1
2 1
输出
0.50
(2)问题分析
不能用可行路径/总路径,因为在边上走概率是1,而在里面走概率是1/2!!!概率题要注意!!!详细每一步可以看代码注释。
(3)完整代码
import java.util.Scanner; /* * 蘑菇阵 */ public class Main { //不能用可行路径/总路径,因为在边上走概率是1,而在里面走概率是1/2!!!概率题要注意 public static void main(String[] args) { Scanner scanner = new Scanner(System.in); while (scanner.hasNext()) { int n = scanner.nextInt(); int m = scanner.nextInt(); int k = scanner.nextInt(); int[][] flag = new int[n][m]; for(int i=0;i<k;i++) { int y = scanner.nextInt() - 1; int x = scanner.nextInt() - 1; flag[y][x] = 1; } System.out.printf("%.2f\n", dpSolve(flag, n, m)); } } public static double dpSolve(int[][] flag, int n, int m) { double[][] dp = new double[n][m]; for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { //初始化 if (flag[i][j] == 1)//有蘑菇概率为0 dp[i][j] = 0; else if (i == 0 && j == 0)//初始位置概率为1 dp[i][j] = 1; else if (n == 1) // 只有一行 dp[i][j] = dp[i][j - 1];//每行概率一样为1 else if (m == 1) // 只有一列 dp[i][j] = dp[i - 1][j];//每列概率一样为1 else if (i == 0)//不在初始位置,不只有一列,里面所有往下走的概率 dp[i][j] = dp[i][j - 1] * 0.5; else if (j == 0)//不在初始位置,不只有一行,里面所有往右走的概率 dp[i][j] = dp[i - 1][j] * 0.5; else if (i == n - 1 && j == m - 1) // 终点 dp[i][j] = dp[i - 1][j] + dp[i][j - 1]; //计算概率 else if (i == n - 1) // 底边 dp[i][j] = dp[i - 1][j] * 0.5 + dp[i][j - 1]; else if (j == m - 1) // 最右边 dp[i][j] = dp[i][j - 1] * 0.5 + dp[i - 1][j]; else // 两种走法,概率分别是0.5 dp[i][j] = dp[i - 1][j] * 0.5 + dp[i][j - 1] * 0.5; } } return dp[n - 1][m - 1]; } }