以所在位置为状态,dp[i] 表示在位置 i 的安全的概率。
dp[i] = p * dp[i-1] + (1 - p) * dp[i-2]; // i 位置没有地雷但是题目数据的范围是 10^8 这样dp的话会 TLE。
想想可以用矩阵快速幂优化。简单退出矩阵是
|p 1-p| * |dp[i] | = |dp[i+1]|
|1 0 | |dp[i-1]| |dp[i] |
而这时地雷位置是不满足这个矩阵的,因此我们得对地雷位置进行特判。而两个地雷中间的位置可以用快速幂优化。
假设 k 位置放有地雷,,我们可以得到 dp[k+1] = dp[k-1] * (1 - p);hint:两个地雷相邻(a[i] + 1 = a[i+1])要特判,直接快速幂的话会TLE。
/***********************************************
** problem ID : poj_3744.cpp
** create time : Fri Jul 31 11:12:39 2015
** auther name : xuelanghu
** auther blog : blog.csdn.net/xuelanghu407
**********************************************/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define rep(i) for (int i=0; i<2; i++)
struct Array {
double m[2][2];
void _set(int c) {
rep(i) rep(j) {
m[i][j] = (i == j) ? c : 0;
}
}
void _show() {
cout << "==============" << endl;
rep(i) {rep(j) cout << m[i][j] << " "; cout << endl;}
}
};
Array _mul (Array a, Array b) {
Array _tmp;
_tmp._set(0.0);
rep(i) rep(j) rep(k) {
_tmp.m[i][j] += a.m[i][k] * b.m[k][j];
}
return _tmp;
}
Array power (Array s, int p) {
Array res;
res._set(1);
for (; p; p >>= 1) {
if (p & 1) res = _mul(res, s);
s = _mul(s, s);
}
return res;
}
int _unique(int a[], int n) {
int j=0;
for (int i=1; i<=n; i++) {
if (a[i] == a[j]) continue;
a[++j] = a[i];
}
return j;
}
int main () {
int N;
int a[12];
double p;
for (; scanf("%d%lf", &N, &p) == 2; ) {
a[0] = 0;
for (int i=1; i<=N; i++) {
scanf ("%d", &a[i]);
}
sort(a, a+N+1);
int K = _unique(a, N);
Array A;
A.m[0][0] = p; A.m[0][1] = 1 - p;
A.m[1][0] = 1.0; A.m[1][1] = 0.0;
bool flag = false;
for (int i=1; i<=K; i++) {
if (a[i] == a[i-1] + 1) flag = true;
}
if (flag) { printf ("%.7f\n", 0.0); continue; }
double res = 1;
Array B;
for (int i=1 ;i<=K; i++) {
B = power(A, a[i] - a[i-1] - 2);
res = res * B.m[0][0] * (1 - p);
}
printf ("%.7f\n", res);
}
return 0;
}版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/xuelanghu407/article/details/47172759