[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;
}

  

posted @ 2016-11-30 18:46  ciao_sora  阅读(214)  评论(0编辑  收藏  举报