您的位置:首页 > 其它

poj3744——Scout YYF I(概率DP+矩阵快速幂)

2017-04-12 21:43 344 查看
Scout YYF I

Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 8564 Accepted: 2510
Description

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

这题很显然了, n个雷,分别在 a[1]...a
 ,走一步概率为 p ,走两步概率为 1-p ,一开始在 1 号位置,问安全到达终点的概率。显然,如果k 号位有雷,那么安全通过这个雷只可能是在 k-1 号位选择走两步到 k+1 号位。因此,可以得到如下结论:在第 i 个雷的被处理掉的概率就是从 a[i-1]+1 号位到 a[i] 号位的概率。于是,可以用 1 减去就可以求出安全通过第 i 个雷的概率,最后乘起来即可,比较悲剧的是数据很大,所以需要用到矩阵快速幂……假设s都是不递减的。
假设dp[i]表示从1到达i这个位置的概率
则:
dp[s[1]-1]为1~s[1]-1的概率//s[1]不能到达
dp[s[2]-1]为1~s[2]-1也是1->s[1]-1->s[1]+1->s[2]-1的概率
由于最多只能跳两格
所以dp[s[i]+1]一定是从dp[s[i]-1]到达
然后从dp[s[i]+1]到达dp[s[i+1]-1];//这部分就可以用矩阵快速幂类似斐波那契数列,有ans[i]=p*ans[i-1]+(1-p)*ans[i-2] ,构造矩阵为
d(i-1) d(i-2) * p 1 = di di-1
0       0         1-p  0       0   0


#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <cmath>
#include <algorithm>
#include <vector>
#include <map>
#include <string>
#include <stack>
using namespace std;
typedef long long ll;
#define PI 3.1415926535897932
#define E 2.718281828459045
#define INF 0x3f3f3f3f
#define mod 100000007

const int M=1005;
int n,m;
int cnt;
int sx,sy,sz;
int mp[1000][1000];
int pa[M*10],rankk[M];
int head[M*6],vis[M*100];
int dis[M*100];
ll prime[M*1000];
bool isprime[M*1000];
int lowcost[M],closet[M];
char st1[5050],st2[5050];
int len[M*6];
typedef pair<int ,int> ac;
//vector<int> g[M*10];
double dp[M][M];
int has[10500];
int month[13]= {0,31,59,90,120,151,181,212,243,273,304,334,0};
int dir[8][2]= {{0,1},{0,-1},{-1,0},{1,0},{1,1},{1,-1},{-1,1},{-1,-1}};

void getpri()
{
    ll i;
    int j;
    cnt=0;
    memset(isprime,false,sizeof(isprime));
    for(i=2; i<1000000LL; i++)
    {
        if(!isprime[i])prime[cnt++]=i;
        for(j=0; j<cnt&&prime[j]*i<1000000LL; j++)
        {
            isprime[i*prime[j]]=1;
            if(i%prime[j]==0)break;
        }
    }
}
struct node
{
    int v,w;
    node(int vv,int ww)
    {
        v=vv;
        w=ww;
    }
};
vector<int> g[M*100];
string str[1000];
//int dp[10000];
//int a[1000],b[1000];
struct Mat
{
    double mat[6][6];
    Mat(double x)
    {
        memset(mat,0,sizeof(mat));
        for(int i=0; i<6; i++)mat[i][i]=x;
    }
};
Mat operator*(const Mat& a,const Mat& b)
{
    Mat c(0);
    int i,j,k;
    for(i=0; i<6; i++)
        for(j=0; j<6; j++)
            for(k=0; k<6; k++)
            {
                c.mat[i][j]=(c.mat[i][j]+a.mat[i][k]*b.mat[k][j]);
            }
    return c;
}
Mat qmod(Mat x,int b)
{
    Mat res(1);
    while(b)
    {
        if(b&1)res=res*x;
        x=x*x;
        b>>=1;
    }
    return res;
}
int a[15];
int main()
{
    int i,j,k,t;
    double p;
    while(~scanf("%d%lf",&n,&p)){
        for(i=1;i<=n;i++)
            scanf("%d",&a[i]);
        //dp[i]=p*dp[i-1]+(1-p)*dp[i-2];第i步碰到雷的概率,也就是说i-1和i-2要安全
        sort(a+1,a+1+n);
        double ans=1;
        Mat tmp(0),ret(0);
        tmp.mat[0][0]=p;
        tmp.mat[0][1]=1;
        tmp.mat[1][0]=1-p;
        tmp.mat[1][1]=0;
        ret=qmod(tmp,a[1]-1);//到a[0]前一步都是安全的
        ans*=(1-ret.mat[0][0]);
        for(i=2;i<=n;i++)
        {
            if(a[i]==a[i-1])continue;
            ret=qmod(tmp,(a[i]-(a[i-1]+1)));
            ans*=(1-ret.mat[0][0]);
        }
        printf("%.7f\n",ans);
    }
    return 0;
}


另一种思路:

http://blog.csdn.net/xuelanghu407/article/details/47172759
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: