对于迷宫:
+----+----+----+----+----+
| |BOMB|BOMB|BOMB| |
+----+----+----+----+----+
|EXIT| S1 | S2 | S3 |BOMB|
+----+----+----+----+----+
| |BOMB|BOMB|BOMB| |
+----+----+----+----+----+
您可以将其映射到每次移动后发生的概率矩阵:
// DEAD, ESC, S1, S2, S3
p = [
[ 1.00, 0.00, 0.00, 0.00, 0.00 ], // DEAD
[ 0.00, 1.00, 0.00, 0.00, 0.00 ], // ESCAPED
[ 0.50, 0.25, 0.00, 0.25, 0.00 ], // S1
[ 0.50, 0.00, 0.25, 0.00, 0.25 ], // S2
[ 0.75, 0.00, 0.00, 0.25, 0.00 ] // S3
];
所以,沿着中间行阅读,如果青蛙从S1 方格开始,那么,经过一跳,有:
- 死亡的概率为 0.5;
- 0.25 它逃脱的概率;和
- 在 S2 中的概率为 0.25。
并且沿着前两行阅读 - 如果它已经死亡/逃脱,那么它将保持死亡/逃脱(分别)的概率为 1。
要计算n 跳跃后的概率,只需将概率矩阵提高到n 的幂。
// DEAD, ESC, S1, S2, S3
p = [
[ 1.00, 0.00, 0.00, 0.00, 0.00 ], // DEAD
[ 0.00, 1.00, 0.00, 0.00, 0.00 ], // ESCAPED
[ 0.50, 0.25, 0.00, 0.25, 0.00 ], // S1
[ 0.50, 0.00, 0.25, 0.00, 0.25 ], // S2
[ 0.75, 0.00, 0.00, 0.25, 0.00 ] // S3
];
function multiply( a, b )
{
if ( a[0].length !== b.length )
{
throw "Matrices must have same a.x/b.y dimensions!";
}
let r = [];
for ( let y = 0; y < a.length; y++ )
{
r[y] = [];
for ( let x = 0; x < b[0].length; x++ )
{
r[y][x] = 0;
for ( let i = 0; i < a[0].length; i++ )
{
r[y][x] += a[y][i] * b[i][x];
}
}
}
return r;
}
// Start at S1
r = [ [ 0, 0, 1, 0, 0 ] ];
// Output probabilities up to 10 decimal places.
dp = 10;
console.log(
"i"
+ " " + "DEAD".padEnd(" ",dp+2)
+ " " + "ESCAPED".padEnd(" ",dp+2)
+ " " + "S1".padEnd(" ",dp+2)
+ " " + "S2".padEnd(" ",dp+2)
+ " " + "S3".padEnd(" ",dp+2)
);
for ( let i = 1; i <= 50; i++ ){
r = multiply( r, p );
if ( i < 10 || i % 10 === 0 )
{
console.log(
i
+ " " + Number(r[0][0]).toFixed(dp)
+ " " + Number(r[0][1]).toFixed(dp)
+ " " + Number(r[0][2]).toFixed(dp)
+ " " + Number(r[0][3]).toFixed(dp)
+ " " + Number(r[0][4]).toFixed(dp)
);
}
}
这个简单的例子表明它很快收敛到青蛙不太可能仍然在移动的状态,并且有0.7321428571 它死了的概率和0.2678571429 它活着的概率。
挑战将是获取输入映射并输出矩阵,然后查看优化矩阵的幂以快速找到该收敛点的方法(通过反复平方矩阵 - p = multiply(p, p); - 或 @ 987654321@).