码迷,mamicode.com
首页 > 其他好文 > 详细

poj 3744 Scout YYF I (矩阵快速幂)

时间:2015-08-04 20:58:12      阅读:105      评论:0      收藏:0      [点我收藏+]

标签:

题意:一条路上有n个地雷,告诉你这n个雷的位置,一个人初始在位置1,这个人每次可以走1个单位或者跳2个单位,概率分别为p和1-p,现在要求这个人安全通过这段路的概率

思路:求出安全通过每个雷的概率,再把所有的乘起来即可。要安全通过某个雷(假设在place[i]这个位置),只有从place[i]-1跳两格才能安全通过。这样只要求出place[i-1]+1到place[i]-1的概率再乘上(1-p)就能得到通过第i个雷的概率。

由于数据较大,所以必须用矩阵快速幂。其实这是斐波拉契数列的一个变形:f(i)=f(i-1)*p+f(i-2)*(1-p) ;要快速求出f(i),使用矩阵快速幂即可。

 

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>

using namespace std;
int place[1010] ;
double ep[1010] , p ,f1 ,f2;
struct Mat{
    double mat[10][10] ;
};

Mat mul(Mat a,Mat b)
{
    Mat ret;
    for(int i=0;i<2;i++)
      for(int j=0;j<2;j++)
      {
          ret.mat[i][j]=0;
          for(int k=0;k<2;k++)
            ret.mat[i][j]+=a.mat[i][k]*b.mat[k][j];
      }
    return ret;
}
Mat pow_M(Mat a,int n)
{
    Mat ret;
    memset(ret.mat,0,sizeof(ret.mat));
    for(int i=0;i<2;i++)ret.mat[i][i]=1;
    Mat temp=a;
    while(n)
    {
        if(n&1)ret=mul(ret,temp);
        temp=mul(temp,temp);
        n>>=1;
    }
    return ret;
}
double Q_mul(int k)
{
    Mat a;
    a.mat[0][0]=p, a.mat[0][1]=1.0-p ,a.mat[1][0]=1.0 ,a.mat[1][1]=0;
    Mat ret=pow_M(a,k);
    return (f2*ret.mat[1][0]+f1*ret.mat[1][1])*(1.0-p);
}
int main()
{
    int n;
    while(cin>>n>>p){
        memset(place,0,sizeof(place)) ;
        for(int i=0;i<n;i++){
            scanf("%d",&place[i]) ;
        }

        sort(place,place+n) ;
        int now=1;
        double ans=1.0;
        if(place[0]==1){
             printf("0.0000000\n") ;
             continue ;
        }
        for(int i=0 ; i<n ; i++){
            //cout<<i<<" "<<place[i]<<" "<<now<<" "<<endl;
            if(place[i] == now){
                now= -1;
                break;
            }
            else{

                f1=1.0;
                if(now +1 == place[i]){
                    //cout<<1<<endl;
                    ep[i] = f1*(1.0-p) ;
                }
                else{
                    f2=f1*(1.0*p) ;
                    ep[i]=Q_mul(place[i]-(now+1)) ;
                    //cout<<place[i]-(now+1)<<endl;
                }
                now=place[i] + 1 ;
            }
        }
        if(now==-1){
            printf("0.0000000\n") ;
        }
        else{
            for(int i=0 ;i <n ; i++){
                //cout<<ep[i]<<endl;
                ans*=ep[i] ;
            }
            printf("%.7f\n",ans) ;
        }
     }
    return 0;
}

 

poj 3744 Scout YYF I (矩阵快速幂)

标签:

原文地址:http://www.cnblogs.com/Scale-the-heights/p/4702990.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!