[poj3744] Scout YYF I【概率dp 数学期望】
传送门:http://poj.org/problem?id=3744
令f(i)表示到i,安全的概率。则f(i) = f(i - 1) * p + f(i - 2) * (1 - p),若i位置有地雷,则f(i) = 0.很显然,要用矩阵来加速,矩阵也很好构造,懒得写了,百度图片搜“poj3744”就能看到。注意一下边界的处理。
#include <cstdio> #include <algorithm> #include <cstring> const int maxn = 15; int n, a[maxn], ima; double p, mtx[2][2] = {{0.5, 0.5}, {1.0, 0.0}}, rt[2][2], tem[2][2], ans[2][2]; inline void mul(double a[2][2], double b[2][2]) { tem[0][0] = a[0][0] * b[0][0] + a[0][1] * b[1][0]; tem[0][1] = a[0][0] * b[0][1] + a[0][1] * b[1][1]; tem[1][0] = a[1][0] * b[0][0] + a[1][1] * b[1][0]; tem[1][1] = a[1][0] * b[0][1] + a[1][1] * b[1][1]; memcpy((void*)b, (void*)tem, sizeof tem); } inline void poww(int mi) { int i; for (i = 31; mi >> i & 1 ^ 1; --i); memcpy((void*)rt, (void*)mtx, sizeof mtx); for (--i; ~i; --i) { mul(rt, rt); if (mi >> i & 1) { mul(mtx, rt); } } } int main(void) { //freopen("in.txt", "r", stdin); while (scanf("%d%lf", &n, &p) != EOF) { mtx[0][0] = p; mtx[0][1] = 1.0 - p; for (int i = 1; i <= n; ++i) { scanf("%d", a + i); } std::sort(a + 1, a + n + 1); n = std::unique(a + 1, a + n + 1) - a - 1;\ for (int i = 1; i <= n; ++i) { if (a[i] - a[i - 1] == 1) { puts("0.0000000"); goto end; } } ans[0][0] = 0.0; ans[1][0] = 1.0 / (1.0 - p); for (int i = 1; i <= n; ++i) { poww(a[i] - a[i - 1] - 1); mul(rt, ans); ans[1][0] = ans[0][0]; ans[0][0] = 0.0; } printf("%.7f\n", ans[0][0] * p + ans[1][0] * (1.0 - p)); end:; } return 0; }