poj 3744 Scout YYF I

题意 : 初始状态 你在 1 这个点上, p 个概率向前走一步, 1-p 的概率 向前有 两步。 现在,线上分布这 n 个雷, 也就是这n 个格子不能走,问成功走出这条路的概率。

n<=10   , 雷的坐标最大是10^8


概率DP :

 考虑到 雷的坐标比较大 ,不可以直接DP ,但是 n 比较小,可以分段,

对没有雷的坐标 x -> y ,   f[ i ] = f[ i -1] *p + f[ i-2 ]*(1 -q)

这样递推, 明显可以矩阵快速幂 递推。复杂度 lg n


注意 : 给的雷 没说排好序  , 没排序 一直TLE ,原因是矩阵快速幂是 指数出现了 负数。。

double 类型记得控eps 避免出现 -0.000000 的状态 。


#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <stack>
#include <cstring>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <assert.h>
#include <queue>
#define REP(i,n) for(int i=0;i<n;i++)
#define TR(i,x) for(typeof(x.begin()) i=x.begin();i!=x.end();i++)
#define ALLL(x) x.begin(),x.end()
#define SORT(x) sort(ALLL(x))
#define CLEAR(x) memset(x,0,sizeof(x))
#define FILLL(x,c) memset(x,c,sizeof(x))
using namespace std;
 
const double eps = 1e-8;

#define LL long long 
#define pb push_back
int a[11];
double p;
int n;
const int maxn = 110;
const  int size =2;
struct Mat{
    double mat[size][size];
    void init(){
        mat[0][0]=0;
        mat[0][1]=1-p;
        mat[1][0]=1;
        mat[1][1]=p;
    }
    void Zero(){
        mat[0][0]=0;
        mat[0][1]=0;
        mat[1][0]=0;
        mat[1][1]=0;
    }
    void show(){
        cout << mat[0][0]<<"  "<<mat[0][1]<<endl; 
         cout << mat[1][0]<<"  "<<mat[1][1]<<endl; 
    }
}E,g;
void init_E(){
        E.mat[0][0]=1;
        E.mat[0][1]=0;
        E.mat[1][0]=0;
        E.mat[1][1]=1;
}
Mat operator*(const Mat &a,const Mat &b){
	Mat c;
	for(int i=0;i<size;i++)
		for(int j=0;j<size;j++){
            c.mat[i][j] = 0;
			for(int k=0;k<size;k++){
				if(fabs(a.mat[i][k])>eps && fabs(b.mat[k][j])>eps)
					c.mat[i][j]=(c.mat[i][j]+a.mat[i][k]*b.mat[k][j]);
			}
		}
	return c;
}
Mat operator+(const Mat &a ,const Mat &b){
	Mat c;
	c.Zero();
	for(int i=0;i<size;i++)
		for(int j=0;j<size;j++){
			c.mat[i][j]=(a.mat[i][j]+b.mat[i][j]);
		}
	return c;
}
Mat operator^(Mat a,int x){
	Mat c=E;
	for(;x;x>>=1){
		if(x&1)
			c=c*a;
		a=a*a;    
	}
	return c;
}
int len;
double st;
double get_ans(){
    a[0] = 0;
    st = 1;
    double ans = 0;
    for(int i=1;i<=n;i++){
        len = a[i]- (a[i-1]+1)-1;
        Mat tmp = g^len;
       // cout << len <<" len "<<endl
        ans = st*tmp.mat[1][1];
        st = ans*(1-p);
    }
    return st;
}
void solve(){
        bool bo = true;
        a[0]=-1;
        for(int i=1;i<=n;i++){
            if(a[i] == a[i-1]+1 || a[i] ==1){
                bo = false;
                break;
            }
        } 
        double a=0;
        if(bo){
              a = get_ans();
        }else{
              a = 0;
            
        }
         printf("%.7f\n",a);
}
int main(){
    init_E();
    while(~scanf("%d",&n)){
        scanf("%lf",&p);
        g.init();
        //cout << g.mat[0][1]<<" ** "<<endl;
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
        }
        sort(a+1,a+n+1);
        solve();
    }
    return 0;
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值