题目描述
现在有两个好友A和B,住在一片长有蘑菇的由n*m个方格组成的草地,A在(1,1),B在(n,m)。现在A想要拜访B,由于她只想去B的家,所以每次她只会走(i,j+1)或(i+1,j)这样的路线,在草地上有k个蘑菇种在格子里(多个蘑菇可能在同一方格),问:A如果每一步随机选择的话(若她在边界上,则只有一种选择),那么她不碰到蘑菇走到B的家的概率是多少?
Java Code
输入描述:
第一行N,M,K(2 ≤ N,M ≤ 20, k ≤ 100),N,M为草地大小,接下来K行,每行两个整数x,y,代表(x,y)处有一个蘑菇。
输出描述:
输出一行,代表所求概率(保留到2位小数)
输入例子:
2 2 1
2 1
输出例子:
0.50
解题
计算有没有蘑菇的路径总和并计算概率,但是这样是不对的

import java.util.Scanner; import java.text.DecimalFormat; public class Main{ public static void main(String[] args){ Scanner in = new Scanner(System.in); DecimalFormat df = new DecimalFormat("#0.00"); int n,m,k; int x,y; while(in.hasNext()){ String[] nmk = in.nextLine().split(" "); n = Integer.valueOf(nmk[0]); m = Integer.valueOf(nmk[1]); k = Integer.valueOf(nmk[2]); int[][] A = new int[n+1][m+1]; while((k--)>0){ String[] xy = in.nextLine().split(" "); x = Integer.valueOf(xy[0]); y = Integer.valueOf(xy[1]); A[x][y] = 1; } long d1 = dp1(n,m); long d2 = dp2(A,n,m); double p = (1.0*d2)/d1; System.out.println(df.format(p)); } } // 不碰到蘑菇的路径数量 // 1 1 到 n m 的所有可能的和 有蘑菇的不走 下标从1 开始 public static long dp2(int[][]A,int n,int m){ long[][] B = new long[n+1][m+1]; for(int i=1;i<=n;i++){ if(A[i][1]==0){ B[i][1] =1; }else break; } for(int j=1;j<=m;j++){ if(A[1][j]==0) B[1][j]=1; else break; } for(int i=2;i<=n;i++){ for(int j=2;j<=m;j++){ B[i][j] = A[i][j]==1?0:(B[i-1][j] + B[i][j-1]); } } return B[n][m]; } // 1 1 到 n m 的所有可能的和 所有的可能路径数量 public static long dp1(int n,int m){ long[][]B = new long[n+1][m+1]; for(int i=1;i<=n;i++) B[i][1] = 1; for(int j=1;j<=m;j++) B[1][j] = 1; for(int i =2;i<=n;i++){ for(int j=2;j<=m;j++) B[i][j] = B[i-1][j] + B[i][j-1]; } return B[n][m]; } }
讨论中看到上面举得例子,所有直接计算路径数是不对,重点是概率不一样。
import java.util.Scanner; import java.text.DecimalFormat; public class Main{ public static void main(String[] args){ Scanner in = new Scanner(System.in); DecimalFormat df = new DecimalFormat("#0.00"); int n,m,k; int x,y; double p; while(in.hasNext()){ String[] nmk = in.nextLine().split(" "); n = Integer.valueOf(nmk[0]); m = Integer.valueOf(nmk[1]); k = Integer.valueOf(nmk[2]); int[][] A = new int[n+1][m+1]; while((k--)>0){ String[] xy = in.nextLine().split(" "); x = Integer.valueOf(xy[0]); y = Integer.valueOf(xy[1]); A[x][y] = 1; } p = dp(A,n,m); System.out.println(df.format(p)); } } public static double dp(int[][] A,int n,int m){ // 到达个点的概率 double[][] B = new double[n+1][m+1]; if(A[1][1] == 1 || A[n][m]==1) return 0.0; B[1][1] = 1.0; for(int i =1;i<=n;i++){ for(int j=1;j<=m;j++){ if(i==1&&j==1) // 起始位置 continue; if(A[i][j] == 1)// 不可走 B[i][j]=0.0; else{ if(j==m) // 最后一列 上到下的概率是1.0 和下面情况累加就是1.0; B[i][j]+=B[i-1][j]*0.5; if(i==n) // 最后一行 B[i][j]+=B[i][j-1]*0.5; B[i][j]+=B[i-1][j]*0.5+B[i][j-1]*0.5; } } } return B[n][m]; } }