您的位置:首页 > 产品设计 > UI/UE

蘑菇阵(动态规划、百度)——unique paths

2016-04-24 13:28 381 查看
题目描述

现在有两个好友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(2 ≤ N,M ≤ 20, k ≤ 100),N,M为草地大小,接下来K行,每行两个整数x,y,代表(x,y)处有一个蘑菇。

输出描述:

输出一行,代表所求概率(保留到2位小数)

输入例子:

2 2 1

2 1

输出例子:

0.50

解题思路:

题目要求的是不碰到蘑菇的概率,一开始我使用路径数的方法来求解的(p=不碰到蘑菇的走法/所有的走法),但是一直都未能通过所有测试。后来认真研究了下题目,也看了些网上的一些资料。题目要求要计算不碰到蘑菇的概率,因为走的概率不均等,如

2 3的蘑菇阵

1 2 3

4 5 6

从1 走到6

1-2的概率为0.5,2-3概率为0.5,3-6概率为1

1-4的概率为0.5,2-5概率为0.5,4-5概率为1,5-6概率为1,3-6概率为1

若走1-2-3-6概率为0.25,1-2-5-6概率为0.25,而走1-4-5-6的概率为0.5

所以三种走法的概率不均等,所以算其不碰到蘑菇的概率不可以用枚举路径数的方法计算。只能往两个方向走,所以两个方向的概率都是0.5,但是在边界处只有一种走法也就是该走法的概率为1,需要单独对边界进行处理。

不是边界的计算不碰到蘑菇的概率:

ways[i][j] = ways[i-1][j] * 0.5 * (map[i-1][j] + 1)%2+ ways[i][j-1] * 0.5 (map[i-1][j] + 1)%2 即为上面和左边的方向过来,前提上面和左边都没有蘑菇

边界的处理:

最底端第n行:ways[i][j] = ways[i][j-1] * (map[i-1][j] + 1)%2

最右边第m列:ways[i][j] = ways[i-1][j] * (map[i-1][j] + 1)%2

public static double getProbability(int map[][], int n, int m) {
double ways[][] = new double
[m];// 没走蘑菇阵的概率
ways[0][0] = 1;

// int ti = 0, tj = 0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {//注意处理单行和单列的问题
if (j == m - 1 && i - 1 >= 0) {// 最右边
ways[i][j] = ways[i - 1][j];
}
if (i == n - 1 && j -1 >=0) {// 最下边
ways[i][j] += ways[i][j - 1];
}
if(i - 1 >= 0)//不止一行
if (map[i - 1][j] != 1 && j != m - 1) {// 往下走的概率
ways[i][j] += ways[i - 1][j] * 0.5;
}
if (j-1 >= 0) {//不止一列
if (map[i][j - 1] != 1 && i != n - 1) {// 往右边走
ways[i][j] += ways[i][j - 1] * 0.5;
}
}

if (map[i][j] == 1) {//如果终点是蘑菇则概率为0
ways[i][j] = 0;
}

}

}

if (map[n - 1][m - 1] == 1) {
ways[n - 1][m - 1] = 0;
}

//      show(ways, n, m);
return ways[n - 1][m - 1];

}


一开始我用路径求解的方法,该路径数方法也是一个动态规划的方法但不适合于蘑菇阵这个题目,将该方法稍微改改就是LeetCode里的两道动态规划题目unique paths和unique paths II

/**
* 用路径法求解概率=可以走的路径/总的路径,算了好久都是错的,因为走的路径概率不一样( ╯□╰ )
*
* @param map
* @param n
* @param m
* @return
*/
public static double getPathNumProbability(int map[][], int n, int m) {
int ways[][][] = new int
[m][3];// 0存储没有走蘑菇的,1存储走蘑菇的,2存储没考虑蘑菇的
ways[0][0][1] = 0;
ways[0][0][0] = 1;
ways[0][0][2] = 1;
for (int i = 1; i < n; i++) {// 首列
ways[i][0][2] = 1;
ways[i][0][0] = ways[i - 1][0][0];
ways[i][0][1] = ways[i - 1][0][1];
if (map[i - 1][0] == 1) {
ways[i][0][1] = 1;
ways[i][0][0] = 0;
}
}
for (int j = 1; j < m; j++) {// 首行
ways[0][j][0] = ways[0][j - 1][0];
ways[0][j][1] = ways[0][j - 1][1];
ways[0][j][2] = 1;
if (map[0][j - 1] == 1) {
ways[0][j][1] = 1;
ways[0][j][0] = 0;
}

}
// int ti = 0, tj = 0;
for (int i = 1; i < n; i++) {
for (int j = 1; j < m; j++) {
ways[i][j][2] = ways[i - 1][j][2];// 往下走
if (map[i - 1][j] == 1) {
ways[i][j][1] = ways[i - 1][j][2];
ways[i][j][0] = 0;
} else {
ways[i][j][1] = ways[i - 1][j][1];
ways[i][j][0] = ways[i - 1][j][0];
}

ways[i][j][2] += ways[i][j - 1][2];// 往右走
if (map[i][j - 1] == 1) {
ways[i][j][1] += ways[i][j - 1][2];
ways[i][j][0] += 0;
} else {
ways[i][j][0] += ways[i][j - 1][0];
ways[i][j][1] += ways[i][j - 1][1];
}
}

}
if (map[n - 1][m - 1] == 1) {

ways[n - 1][m - 1][0] = 0;
}
// System.out.println("ways[n-1][m-1][2] "+ways[n-1][m-1][2]+" 00
// "+ways[n-1][m-1][0]+" 11 "+ways[n-1][m-1][1]);
// show(ways,n,m);
return ways[n - 1][m - 1][0] * 1.0 / ways[n - 1][m - 1][2];

}


leetcode unique paths

/**
*
* leetcode unique paths
* A robot is located at the top-left corner of a m x n grid (marked 'Start'
* in the diagram below).
*
* The robot can only move either down or right at any point in time. The
* robot is trying to reach the bottom-right corner of the grid (marked
* 'Finish' in the diagram below).
*
* How many possible unique paths are there?
*
*
* Above is a 3 x 7 grid. How many possible unique paths are there?
*
* @param m
* @param n
* @return
*/
public int uniquePaths(int m, int n) {
int map[][] = new int[m]
;
int ways[][] = new int
[m];//
ways[0][0] = 1;
for (int i = 1; i < n; i++) {// 首列
ways[i][0] = 1;
}
for (int j = 1; j < m; j++) {// 首行
ways[0][j] = 1;
}
// int ti = 0, tj = 0;
for (int i = 1; i < n; i++) {
for (int j = 1; j < m; j++) {
ways[i][j] = ways[i - 1][j];// 往下走
ways[i][j] += ways[i][j - 1];// 往右走
}
}
return ways[n - 1][m - 1];
}


稍微改改就是leetcode Unique Paths II 的解

* leetcode Unique Paths II Follow up for "Unique Paths":
*
* Now consider if some obstacles are added to the grids. How many unique
* paths would there be?
*
* An obstacle and empty space is marked as 1 and 0 respectively in the
* grid.
*
* For example, There is one obstacle in the middle of a 3x3 grid as
* illustrated below.
*
* [ [0,0,0], [0,1,0], [0,0,0] ] The total number of unique paths is 2.
*
* @param map
* @param n
* @param m
* @return
*/
public int uniquePathsWithObstacles(int[][] obstacleGrid) {
int n = obstacleGrid.length, m = obstacleGrid[0].length;
int ways[][][] = new int
[m][3];// 0存储没有走障碍的,1存储走障碍的,2存储没考虑障碍的
ways[0][0][1] = 0;
ways[0][0][0] = 1;
ways[0][0][2] = 1;
for (int i = 1; i < n; i++) {// 首列
ways[i][0][2] = 1;
ways[i][0][0] = ways[i - 1][0][0];
ways[i][0][1] = ways[i - 1][0][1];
if (obstacleGrid[i - 1][0] == 1) {
ways[i][0][1] = 1;
ways[i][0][0] = 0;
}

}
for (int j = 1; j < m; j++) {// 首行
ways[0][j][0] = ways[0][j - 1][0];
ways[0][j][1] = ways[0][j - 1][1];
ways[0][j][2] = 1;
if (obstacleGrid[0][j - 1] == 1) {
ways[0][j][1] = 1;
ways[0][j][0] = 0;
}

}
// int ti = 0, tj = 0;
for (int i = 1; i < n; i++) {
for (int j = 1; j < m; j++) {
ways[i][j][2] = ways[i - 1][j][2];// 往下走
if (obstacleGrid[i - 1][j] == 1) {
ways[i][j][1] = ways[i - 1][j][2];
ways[i][j][0] = 0;
} else {
ways[i][j][1] = ways[i - 1][j][1];
ways[i][j][0] = ways[i - 1][j][0];
}

ways[i][j][2] += ways[i][j - 1][2];// 往右走
if (obstacleGrid[i][j - 1] == 1) {
ways[i][j][1] += ways[i][j - 1][2];
ways[i][j][0] += 0;
} else {
ways[i][j][0] += ways[i][j - 1][0];
ways[i][j][1] += ways[i][j - 1][1];
}
}

}
if (obstacleGrid[n - 1][m - 1] == 1) {

ways[n - 1][m - 1][0] = 0;
}
// System.out.println("ways[n-1][m-1][2] "+ways[n-1][m-1][2]+" 00
// "+ways[n-1][m-1][0]+" 11 "+ways[n-1][m-1][1]);
// show(ways,n,m);
return ways[n - 1][m - 1][0];
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: