Poj--3744(概率DP,矩阵)
2015-01-02 22:16:19
思路:简单的概率DP递推,要用矩阵来加速。
转移方程很简单:dp[i + 2] = P * dp[i + 1] + (1 - P) * dp[i]
转移矩阵:
0 1 dp(i)
(1-P) P dp(i+1)
1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <cmath> 5 #include <vector> 6 #include <map> 7 #include <set> 8 #include <stack> 9 #include <queue> 10 #include <iostream> 11 #include <algorithm> 12 using namespace std; 13 #define lp (p << 1) 14 #define rp (p << 1|1) 15 #define getmid(l,r) (l + (r - l) / 2) 16 #define MP(a,b) make_pair(a,b) 17 typedef long long ll; 18 typedef unsigned long long ull; 19 typedef pair<int,int> pii; 20 const int INF = (1 << 30) - 1; 21 22 int N,pos[20]; 23 double P; 24 25 struct Mx{ 26 double a[2][2]; 27 void clear(){ memset(a,0,sizeof(a));} 28 void stand(){ clear(); for(int i = 0; i < 2; ++i) a[i][i] = 1.0;} 29 Mx operator * (Mx b){ 30 Mx c; c.clear(); 31 for(int i = 0; i < 2; ++i) 32 for(int j = 0; j < 2; ++j) 33 for(int k = 0; k < 2; ++k) 34 c.a[i][j] += a[i][k] * b.a[k][j]; 35 return c; 36 } 37 }; 38 39 Mx Pow(int num){ 40 Mx res; res.stand(); 41 Mx tr; tr.clear(); 42 tr.a[0][1] = 1.0; 43 tr.a[1][0] = 1.0 - P; 44 tr.a[1][1] = P; 45 while(num){ 46 if(num & 1) res = res * tr; 47 tr = tr * tr; 48 num >>= 1; 49 } 50 return res; 51 } 52 53 int main(){ 54 while(scanf("%d%lf",&N,&P) != EOF){ 55 for(int i = 1; i <= N; ++i){ 56 scanf("%d",&pos[i]); 57 } 58 sort(pos + 1,pos + N + 1); 59 Mx ans; ans.clear(); 60 ans.a[0][0] = 1.0; 61 ans.a[1][0] = P; 62 pos[0] = 1; 63 for(int i = 1; i <= N; ++i){ 64 ans = Pow(pos[i] - pos[i - 1]) * ans; 65 ans.a[1][0] -= ans.a[0][0] * P; 66 ans.a[0][0] = 0.0; 67 } 68 printf("%.7f\n",ans.a[1][0]); 69 } 70 return 0; 71 }