zoukankan      html  css  js  c++  java
  • POJ 3744 Scout YYF I 概率dp+矩阵快速幂

    题目链接:

    http://poj.org/problem?id=3744

    Scout YYF I

    Time Limit: 1000MS
    Memory Limit: 65536K
    #### 问题描述 > 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.

    输入

    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].

    输出

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

    样例输入

    1 0.5
    2
    2 0.5
    2 4

    样例输出

    0.5000000
    0.2500000

    题意

    一个人从1号节点出发向右走,有n个位子有地雷,这个人走一步的概率为p,走两步的概率为1-p,现在问这个人安全走过去的概率为多少。

    题解

    由于雷很少,所以可以单独处理下有地雷的位置的时候的转移,比如x的位置有雷,那么就有dp[x+1]=dp[x-1]*(1-p),dp[x+2]=dp[x+1]*p,。其他一整片没有雷的就直接矩阵快速幂干过去(类似于斐波那契数列),起始位置的概率为1.0,然后模拟扫过去求出dp[last+1]就可以了(last指最后一个雷的位置)。

    代码

    #include<map>
    #include<set>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<ctime>
    #include<vector>
    #include<cstdio>
    #include<string>
    #include<bitset>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<functional>
    using namespace std;
    #define X first
    #define Y second
    #define mkp make_pair
    #define lson (o<<1)
    #define rson ((o<<1)|1)
    #define mid (l+(r-l)/2)
    #define sz() size()
    #define pb(v) push_back(v)
    #define all(o) (o).begin(),(o).end()
    #define clr(a,v) memset(a,v,sizeof(a))
    #define bug(a) cout<<#a<<" = "<<a<<endl
    #define rep(i,a,b) for(int i=a;i<(b);i++)
    #define scf scanf
    #define prf printf
    
    typedef __int64 LL;
    typedef vector<int> VI;
    typedef pair<int,int> PII;
    typedef vector<pair<int,int> > VPII;
    
    const int INF=0x3f3f3f3f;
    const LL INFL=0x3f3f3f3f3f3f3f3fLL;
    const double eps=1e-9;
    
    const double PI = acos(-1.0);
    
    //start----------------------------------------------------------------------
    
    const int maxn=2;
    
    struct Matrix{
        double mat[maxn][maxn];
        Matrix(){ clr(mat,0); }
        friend Matrix operator *(const Matrix& A,const Matrix& B){
            Matrix ret;
            for(int i=0;i<maxn;i++){
                for(int j=0;j<maxn;j++){
                    for(int k=0;k<maxn;k++){
                        ret.mat[i][j]=ret.mat[i][j]+A.mat[i][k]*B.mat[k][j];
                    }
                }
            }
            return ret;
        }
    }I;
    
    Matrix pow(Matrix A,int n){
        Matrix ret=I;
        while(n){
            if(n&1) ret=ret*A;
            A=A*A;
            n/=2;
        }
        return ret;
    }
    
    int n;
    double p;
    
    int main() {
        rep(i,0,maxn) I.mat[i][i]=1;
        while(scf("%d%lf",&n,&p)==2&&n){
            vector<int> arr;
            rep(i,0,n){
                int x; scf("%d",&x);
                arr.pb(x);
            }
    
            sort(all(arr));
    
            arr.erase(unique(all(arr)),arr.end());
    
            if(arr.sz()==0){ prf("1.0000000
    "); continue; }
    
            bool su=true;
            if(arr[0]==1) su=false;
            else{
                for(int i=0;i<arr.sz()-1;i++){
                    if(arr[i+1]-arr[i]==1){
                        su=false; break;
                    }
                }
            }
    
            if(!su){ prf("0.0000000
    "); continue; }
    
            Matrix A;
            A.mat[0][0]=p, A.mat[0][1]=1-p;
            A.mat[1][0]=1, A.mat[1][1]=0;
    
            double pre=1.0;
            for(int i=0;i<arr.sz();i++){
                int cnt;
                if(i==0) cnt=arr[i]-1;
                else cnt=arr[i]-arr[i-1]-1;
    
                if(cnt==1){ pre*=(1-p); }
                else{
                    double f0=pre,f1=pre*p;
    
                    Matrix vec;
                    vec.mat[0][0]=pre*p;
                    vec.mat[1][0]=pre;
    
                    vec=pow(A,cnt-2)*vec;
                    pre=vec.mat[0][0];
    
                    pre*=(1-p);
                }
            }
    
            prf("%.7f
    ",pre);
        }
        return 0;
    }
    
    //end-----------------------------------------------------------------------
  • 相关阅读:
    Ubuntu下SVN命令行递归加入文件夹文件(免去一个一个的加入 --force)
    oschina插件和扩展
    oschina iOS代码库
    oschina 开发工具
    oschina应用工具
    oschina程序开发
    网络爬虫 kamike.collect
    WebFetch 是无依赖极简网页爬取组件
    commoncrawl 源码库是用于 Hadoop 的自定义 InputFormat 配送实现
    JAVA平台上的网络爬虫脚本语言 CrawlScript
  • 原文地址:https://www.cnblogs.com/fenice/p/5979281.html
Copyright © 2011-2022 走看看