蘑菇陣

問題描述:
* 現在有兩個好友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)處有一個蘑菇。 
解題思路(DP):
問題表示:1.用map[N][M]表示n*m的草地,將有蘑菇的地方做上標記。
                   2.用P[i][j]來表示每個點不遇到蘑菇的概率。則原點概率顯然爲1。
問題的關鍵:如何利用P[0][0]一步步dp到終點n,m?    
我們可以把問題分類(主要是考慮邊界):
     1.首先,對於第一行的點,它的前一個點只能來自左邊。P[i][j-1]中存儲了左邊的點沒有碰到蘑
        菇的概率。而對第一行來說,我們當前考察的這個左邊點,選擇走當前點這條路徑的概率是0.
        5。因此,第一行的點P[i][j] = P[i][j - 1]*0.5。
     2.同理,第一列的點P[i][j] = P[i - 1][j] * 0.5。
     3.我們很清楚,不管是第一行還是第一列的點,他的前一個點總是有兩種選擇的,可以選左/
        右。但是某些點情況就不同了,他們就是走到最右邊的和走到最下面的。
     4.對於走到最右邊的點,P[i][j] = P[i - 1][j]*1.0 + P[i][j - 1]*0.5。
     5.上面的表達式其實對終點還不成立,我們可以將表達式優化爲:
        p[i][j] = p[i - 1][j]* (j == m-1? 1.0:0.5) +
                 p[i][j - 1]* (i == n-1? 1.0:0.5);  
package nowcoder;
import java.util.Scanner;
/**
 * 現在有兩個好友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)處有一個蘑菇。
 * 
 * 特別提示:有蘑菇路徑數/總路徑數是不對的,因爲每條路的概率不同。
 * 
 * @ClassName: Mushroom
 * @Version 1.0 
 * @Copyright 
 * @date 2017年5月2日 下午1:40:16
 * @description
 */
public class Mushroom {
	public static void main(String[] args) {
		Scanner scan = new Scanner(System.in);
		int n,m,k;  //終點,B的家,k個蘑菇
		n = scan.nextInt();
		m = scan.nextInt();
		k = scan.nextInt();
		boolean map[][] = new boolean[n][m]; //地圖
		int q = 0;
		while(q < k) {
			int x = scan.nextInt();
			int y = scan.nextInt();
			map[x -1][y-1] = true;  //此處有蘑菇
			q++;
		}
		scan.close();
		
		//動態規劃,p[i][j]表示在i,j不遇到蘑菇的概率
		double p[][] = new double[n][m];
		p[0][0] = 1.0; //起點
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < m; j++) {
				//此處有蘑菇
				if(map[i][j] == true) {
					p[i][j] = 0;
				} 
				else if(i==0 && j==0) { //起點不管
					continue;
				}
				else if(i== 0) {
					p[i][j] = p[i][j-1] * 0.5;
				} else if(j == 0) {
					p[i][j] = p[i-1][j] * 0.5;
					
				//i,j處無蘑菇,他前面也無蘑菇的概率,由上/左兩條路決定
				//對於上面的路,如果它處於m-1列,則只能往下走,概率乘1
				//對於左邊的路,如果他處於第n-1行,則只能往右走,概率乘1
				} else {
					p[i][j] = p[i - 1][j]* (j == m-1? 1.0:0.5) +
							  p[i][j - 1]* (i == n-1? 1.0:0.5);
				}			
			}
		}
		
		System.out.println(String.format("%.2f",p[n-1][m-1]));
	}
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章