题目解析
- 该题类似于走迷宫,蘑菇代表不能走通,但不同的是,迷宫可以向前后左右四个方向移动,但该题走的方式只能向右或者向下两个方向移动,注意:右边界处只能向一个方向移动,因此走不通路径的概率是不相等的。比如:M = 2 N = 3
- 1 2 3
- 4 5 6
- 在1时:既可向右走到2,也可向下走到4,因此从1-->2 和从1-->4的概率均为0.5
- 在2时:即可向右走到3,也可向下走到5,因此从2-->3和从2-->5的概率均为0.5
- 在3时:只能走到6,因此从3-->6概率为1
- 在4、5、6时,只能向右走,因此4-->5和5-->6的概率均为1。
通过以上分析,可以得到:
- 假设P(i, j)表示从起点到(i, j)不踩到蘑菇的概率,那么该位置一定是从(i-1, j)或者(i, j-1)处走过来的。而从(i-1, j)或者(i, j-1)到达(i, j)的概率是不等的,比如:如果i或者j在边界,只能向一个方向移动,此时走到(i, j)位置的概率为1,当i或者j不在边界时,走到(i,j)的概率分别为0.5,因此可得出:
- P(i,j) = P(i-1, j) * (i==M? 1 : 0.5)+ P(i, j-1) * (j==N? 1 : 0.5);
- 如果(i, j)为蘑菇时,表示不能走到该位置
解题思路
- 循环接受输入
- 按照输入构造蘑菇地图(二维矩阵),1代表蘑菇,0代表通路,因起点是从(1,1)开始,矩阵多给一个行和列
- 构造用来保存走到(i,j)位置不遇到蘑菇的概率容器
- 按照上述分析结论:遍历蘑菇地图,当遇到蘑菇时,将概率置为0,即不可能到达该位置
- 按照要求输出:注意保留两位精度。
代码
/* 使用动态规划 */
#include<iostream>
#include <iomanip>
#include<algorithm>
#include<vector>
using namespace std;
int main()
{
int n, m, k;
while (cin >> n >> m >> k)
{
// 用来保存蘑菇地图
vector<vector<int> > table((n + 1), vector<int>(m + 1));
// 构造蘑菇地图
int x, y;
for (int i = 0; i < k; i++)
{
cin >> x >> y;
table[x][y] = 1;
}
//P[i][j]表示不碰到蘑菇走到i,j的概率
vector<vector<double> > P((n + 1), vector<double>(m + 1));
P[1][1] = 1.0;// 起点概率为0
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
if (!(i == 1 && j == 1))
{
P[i][j] = P[i - 1][j] * (j == m ? 1 : 0.5) + P[i][j - 1] * (i == n ? 1 : 0.5);
//边界的时候,概率为1
if (table[i][j] == 1) P[i][j] = 0;
//如果该点有蘑 菇,概率置为0
}
}
}
cout << fixed << setprecision(2) << P[n][m] << endl;
}
}