您的位置:首页 > 其它

POJ 3744 Scout YYF I(概率DP+矩阵快速幂)

2015-10-15 12:56 357 查看
题意:有一段路,路上有n个雷,问不踩到雷安全通过这段路的概率,每次可以走一步或两步,走一步的概率为P,走两步的概率为1-P.

思路:如果这段路上只有一个雷且雷在终点的话,那么到达每个点i的概率可以递推得来,p[i] = P*p[i-1] + (1-P)*p[i-2],现在的问题是路上有许多雷,不能直接这么做,那么我们可以考虑将这段路分成n部分,每部分的终点是一颗雷,对每一段分别求出能通过这段路的概率然后相乘即可。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<vector>
#include<map>
#include<queue>
#include<stack>
#include<string>
#include<map>
#include<set>
#include<ctime>
#define eps 1e-6
#define LL long long
#define pii pair<int, int>
//#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;

//const int MAXN = 5000000 + 5;
//const int INF = 0x3f3f3f3f;
int n, a[20];
double p, pass[20];
struct Matrix {
double a[2][2];
Matrix() {
a[0][0] = a[1][1] = 1;
a[0][1] = a[1][0] = 0;
}
void clear() {
a[0][0] = p;
a[0][1] = 1-p;
a[1][0] = 1;
a[1][1] = 0;
}
Matrix operator * (const Matrix& b) const {
Matrix tmp;
tmp.a[0][0] = tmp.a[0][1] = tmp.a[1][0] = tmp.a[1][1] = 0;
for(int i = 0; i < 2; i++)
for(int j = 0; j < 2; j++)
for(int k = 0; k < 2; k++) tmp.a[i][j] += a[i][k]*b.a[k][j];
return tmp;
}
Matrix operator ^ (int k) {
Matrix ans, tmp = *this;
while(k) {
if(k&1) ans = ans * tmp;
k >>= 1;
tmp = tmp * tmp;
}
return ans;
}
};
int main() {
//freopen("input.txt", "r", stdin);
while(scanf("%d", &n) != EOF) {
scanf("%lf", &p);
for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
sort(a+1, a+n+1);
for(int i = 1; i <= n; i++) {
int loop = a[i] - a[i-1] - 1;
Matrix tmp;
tmp.clear();
tmp = tmp ^ loop;
pass[i] = 1 - tmp.a[0][0];
//printf("%.7f\n", tmp.a[0][0]);
}
double ans = 1;
for(int i = 1; i <= n; i++) ans *= pass[i];
printf("%.7f\n", ans);
}
return 0;
}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息