| Time Limit: 1000MS | Memory Limit: 65536K | |
| Total Submissions: 5153 | Accepted: 1404 |
Description
Input
Output
Sample Input
1 0.5 2 2 0.5 2 4
Sample Output
0.5000000 0.2500000
给n个有地雷的位置,给出走1步的概率和2步的概率,求能顺利通过这条路的概率。
首先对这n个点相邻两点排序分段[1,a[0]],[a[0]+1,a[1]] .......,假设k点有地雷,那么这个人肯定走k+1点,那么把n个点分成n段,每段起点的概率都相同,最后把每段不走地雷点的概率相乘就是结果。
由于区间长度特别大,不能O(n)递推,要用矩阵快速幂优化,很容易推出递推公式f(n)=f(n-1)*p+f(n-2)*(1-p),n点只能从n-1点和n-2点到。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
struct matrix
{
double ma[4][4];
};
matrix multi(matrix x,matrix y)
{
matrix ans;
memset(ans.ma,0,sizeof(ans.ma));
for(int i=1; i<=2; i++)
{
for(int j=1; j<=2; j++)
{
if(x.ma[i][j])
{
for(int k=1; k<=2; k++)
ans.ma[i][k]=ans.ma[i][k]+x.ma[i][j]*y.ma[j][k];
}
}
}
return ans;
}
matrix pow(matrix a,int m)
{
matrix ans;
for(int i=1; i<=2; i++)
{
for(int j=1; j<=2; j++)
{
if(i==j)
ans.ma[i][j]=1;
else
ans.ma[i][j]=0;
}
}
while(m)
{
if(m&1)
ans=multi(ans,a);
a=multi(a,a);
m=m>>1;
}
return ans;
}
int main()
{
int a[15];
int n;
double p;
while(~scanf("%d%lf",&n,&p))
{
double ans=1;
matrix b,d;
matrix c;
for(int i=0; i<n; i++)
scanf("%d",&a[i]);
sort(a,a+n);
b.ma[1][1]=p;
b.ma[1][2]=1-p;
b.ma[2][1]=1;
b.ma[2][2]=0;
memset(c.ma,0,sizeof(c.ma));
c.ma[1][1]=p;
c.ma[2][1]=1;
if(a[0]==1||a[0]==2)
{
if(a[0]==1)
ans=0;
else
ans=ans*(1-p);
}
else
{
d=pow(b,a[0]-2);
d=multi(d,c);
ans=ans*(1-d.ma[1][1]);
}
for(int i=1; i<n; i++)
{
int temp=a[i]-a[i-1];
if(temp==1||temp==2)
{
if(temp==1)
ans=0;
else
ans=ans*(1-p);
}
else
{
d=pow(b,temp-2);
d=multi(d,c);
ans=ans*(1-d.ma[1][1]);
}
}
printf("%.7f\n",ans);
}
return 0;
}
poj 3744 Scout YYF I(矩阵优化概率DP)
原文:http://blog.csdn.net/caduca/article/details/40742383