zoukankan      html  css  js  c++  java
  • POJ3744 Scout YYF I (矩阵优化的概率DP)

    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
    ",ans);
    63     }
    64 }
     
  • 相关阅读:
    怎么对Navicat for Oracle 调试
    老版本的java代码与新代码如何找出差异
    Oracle 外部表是做什么用的
    如何在Navicat 中编辑和记录
    如何使用文件对比工具文件夹比较会话菜单
    哪些工具可以用来进行Bug管理
    5类开发者须知的工具
    怎么找出代码之间的差异
    Beyond Compare不仅可以修改网页代码
    文件对比工具有哪些用途
  • 原文地址:https://www.cnblogs.com/fengzhiyuan/p/7673860.html
Copyright © 2011-2022 走看看