1. 程式人生 > >POJ3744 Scout YYF I (矩陣優化的概率DP)

POJ3744 Scout YYF I (矩陣優化的概率DP)

() struct ges single com 因此 pro over col

Scout YYF I YYF is a couragous scout. Now he is on a dangerous mission which is to penetrate into the enemy‘s base. After overcoming a series difficulties, YYF is now at the start of enemy‘s famous "mine road". This is a very long road, on which there are numbers of mines. At first, YYF is at step one. For each step after that, YYF will walk one step with a probability of p
, or jump two step with a probality of 1- p. Here is the task, given the place of each mine, please calculate the probality that YYF can go through the "mine road" safely.

Input

The input contains many test cases ended with EOF.
Each test case contains two lines.
The First line of each test case is N
(1 ≤ N ≤ 10) and p (0.25 ≤ p ≤ 0.75) seperated by a single blank, standing for the number of mines and the probability to walk one step.
The Second line of each test case is N integer standing for the place of N mines. Each integer is in the range of [1, 100000000].

Output

For each test case, output the probabilty in a single line with the precision to 7 digits after the decimal point.

Sample Input

1 0.5
2
2 0.5
2 4

Sample Output

0.5000000
0.2500000

一位童子兵要穿過一條路,路上有些地方放著地雷。這位童子兵非常好玩,走路一蹦一跳的。
每次他在 i 位置有 p 的概率走一步到 i+1 ,或者 (1-p) 的概率跳一步到 i+2。童子兵初始在1位置,求他安全通過這條道路的概率。
以所在位置為狀態,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);
對於炸彈位置為 a[i] 和 a[i+1] 之間的數,知道 dp[a[i]+1] 後可以推出
技術分享
(視0位置有顆地雷,有地雷的位置的dp值為0)
於是我們可以對兩個前後兩個地雷之間用快速冪優化,並最終得到答案dp[max(a[i])+1];
轉自:http://blog.csdn.net/xuelanghu407/article/details/47172759

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<iostream>
 5 #include<cmath>
 6 using namespace std;
 7 
 8 int n;double p;
 9 int x[30];
10 
11 struct Node{double mat[2][2];};
12 Node mul(Node a,Node b)
13 {
14     Node res;
15     for(int i=0;i<2;i++)
16       for(int j=0;j<2;j++)
17       {
18           res.mat[i][j]=0;
19           for(int k=0;k<2;k++) res.mat[i][j]+=a.mat[i][k]*b.mat[k][j];
20       }
21     return res;
22 }
23 Node pow_M(Node a,int n)
24 {
25     Node res;
26     memset(res.mat,0,sizeof(res.mat));
27     for(int i=0;i<2;i++)
28         res.mat[i][i]=1;
29     Node temp=a;
30     while(n)
31     {
32         if(n&1)res=mul(res,temp);
33         temp=mul(temp,temp);
34         n>>=1;
35     }
36     return res;
37 }
38 int main()
39 {
40     while(~scanf("%d%lf",&n,&p))
41     {
42         for(int i=0;i<n;i++)
43             scanf("%d",&x[i]);
44         sort(x,x+n);
45         double ans=1;
46         Node tt;
47         tt.mat[0][0]=p;
48         tt.mat[0][1]=1-p;
49         tt.mat[1][0]=1;
50         tt.mat[1][1]=0;
51         Node temp;
52 
53         temp=pow_M(tt,x[0]-1);
54         ans*=(1-temp.mat[0][0]);
55 
56         for(int i=1;i<n;i++)
57         {
58             if(x[i]==x[i-1])continue;
59             temp=pow_M(tt,x[i]-x[i-1]-1);
60             ans*=(1-temp.mat[0][0]);
61         }
62         printf("%.7f\n",ans);
63     }
64 }

 

POJ3744 Scout YYF I (矩陣優化的概率DP)