1. 程式人生 > >poj 3744 Scout (Another) YYF I - 概率與期望 - 動態規劃 - 矩陣快速冪

poj 3744 Scout (Another) YYF I - 概率與期望 - 動態規劃 - 矩陣快速冪

遞推 cto bits dig min ability 構建 nes text

(Another) 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, (Another) 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, (Another) YYF is at step one. For each step after that, (Another) 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 (Another) 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

  首先表示我被黑了。。出題人好過分。。簡直跟我有仇,不僅黑了一道題,而且還黑了一套題。。

  題目大意 另一個叫做yyf的人在一個數軸上,他在位置1,每次他有p的概率向右跳1格,有(1 - p)的概率向右跳2格,如果踩到地雷就死了,問生還的概率。

  顯然動態規劃。當位置i沒有地雷的時候,顯然有

技術分享

  如果位置i有地雷,那麽有

技術分享

  由於值域很大,所以按照遞推式動態規劃的通用套路:構建轉移矩陣加快動態規劃。

  由於n很小,所以可以分段,段內用矩陣快速冪處理,然後特殊處理一下f[i],繼續往前。

  現在來構建轉移矩陣:

技術分享

Code

  1 /**
  2  * poj
  3  * Problem#3744
  4  * Accepted
  5  * Time: 0ms
  6  * Memory: 232k 
  7  */
  8 #include <iostream>
  9 #include <fstream>
 10 #include <sstream>
 11 #include <cstdio>
 12 #include <cstdlib>
 13 #include <cstring>
 14 #include <cmath>
 15 #include <ctime>
 16 #include <cctype>
 17 #include <algorithm>
 18 #include <set>
 19 #include <map>
 20 #include <vector>
 21 #include <queue>
 22 #include <stack>
 23 #include <bitset>
 24 #include <cassert>
 25 #ifndef WIN32
 26 #define Auto "%lld"
 27 #else
 28 #define Auto "%I64d"
 29 #endif
 30 using namespace std;
 31 typedef bool boolean;
 32 #define clra(a) memset(a, false, sizeof(a))
 33 const signed int inf = ((~0u) >> 1);
 34 #define smin(a, b) a = min(a, b)
 35 #define smax(a, b) a = max(a, b)
 36 
 37 template <typename T>
 38 class Matrix {
 39     public:
 40         T a[2][2];
 41         int row; 
 42         int col;
 43         
 44         Matrix() {        }
 45         Matrix(int row, int col):row(row), col(col) {        }
 46         
 47         Matrix<T> operator * (Matrix<T> b) {
 48             Matrix<T> rt(row, b.col);
 49             assert(col == b.row);
 50             for(int i = 0; i < row; i++)
 51                 for(int j = 0; j < b.col; j++) {
 52                     rt[i][j] = 0;
 53                     for(int k = 0; k < col; k++)
 54                         rt[i][j] += a[i][k] * b[k][j];
 55                 }
 56             return rt;
 57         } 
 58         
 59         T* operator [] (int pos) {
 60             return &a[pos][0];
 61         }
 62 };
 63 
 64 int n;
 65 double p;
 66 Matrix<double> unit(2, 2);
 67 Matrix<double> trans(2, 2);
 68 int boom[15];
 69 
 70 template <typename T>
 71 Matrix<T> matpow(Matrix<T>& a, int pos) {
 72     if(pos == 0)    return unit;
 73     if(pos == 1)    return a;
 74     Matrix<T> temp = matpow(a, pos >> 1);
 75     temp = temp * temp;
 76     if(pos & 1)    temp = temp * a;
 77     return temp;
 78 }
 79 
 80 inline void prepare() {
 81     unit[0][0] = unit[1][1] = 1;
 82     unit[0][1] = unit[1][0] = 0;
 83 }
 84 
 85 inline void init() {
 86     for(int i = 0; i < n; i++)
 87         scanf("%d", boom + i);
 88     sort(boom, boom + n);
 89     trans[0][0] = p, trans[0][1] = 1 - p;
 90     trans[1][0] = 1, trans[1][1] = 0;
 91 }
 92 
 93 inline void solve() {
 94     int last = boom[n - 1];
 95     Matrix<double> f(2, 1);
 96     f[0][0] = 0, f[1][0] = 1;
 97     for(int i = n - 2; ~i; f[0][0] = 0, last = boom[i], i--)
 98         f = matpow(trans, last - boom[i]) * f;
 99     f = matpow(trans, last - 1) * f;
100     printf("%.7lf\n", f[0][0]);
101 }
102 
103 int main() {
104     prepare();
105     while(~scanf("%d%lf", &n, &p)) {    //坑啊,scanf交G++ WA了,交C++過了 
106         init();
107         solve();
108     }
109     return 0;
110 }

poj 3744 Scout (Another) YYF I - 概率與期望 - 動態規劃 - 矩陣快速冪