Description
Input
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
Sample Input
1 0.5 2 2 0.5 2 4
Sample Output
0.5000000 0.2500000
题意:
有一段路,路上有n个陷阱,每一次只能向前走一步或者两步,求安全走过这段路的改路
分析:
设dp[i]表示安全走过第i个陷阱的概率
那么dp[i+1]=dp[i]*(1-p(走到第i+1个陷阱))
因为每次只能走一步或者两步,所有安全走过第i个陷阱后的位置一定在a[i]+1;\
其中a[i]表示第i个陷阱的位置
求从a[i]+1,走到a[i+1]的概率的时候我们需要用到矩阵来经行优化
ans[i]表示走到位置i的概率
ans[i] = p*ans[i-1]+(1-p)*ans[i-2];
ans[0]=0,ans[1]=1;
都说G++比C++要好,但是本题最好用C++提交。
如果用G++提交,浮点型输出一定要用%f,否则会WA。
这是因为G++标准的浮点型输出用%f,而不是%lf。
#include <iostream> #include <stdio.h> #include <stdlib.h> #include <algorithm> #include <math.h> #include <string.h> using namespace std; const int maxn=15; int cnt[maxn]; double dp[maxn]; double p; int n; struct matrix { double data[2][2]; }; matrix I={1,0,0,1}; matrix multi(matrix a,matrix b) { matrix c; memset(c.data,0,sizeof(c.data)); for(int i=0;i<2;i++) for(int j=0;j<2;j++) for(int k=0;k<2;k++) c.data[i][j]+=a.data[i][k]*b.data[k][j]; return c; } double pow(matrix a,int b) { matrix ans=I; while(b) { if(b&1) { ans=multi(ans,a); b--; //减比不减更好 虽然都对 但是减了更好理解一点 } b>>=1; a=multi(a,a); } return ans.data[0][0]; } int main() { while(cin>>n>>p) { memset(dp,0,sizeof(dp)); //该初始化的地方一定要初始化 cnt[0]=0; //为第一个雷做准备的 for(int i=1;i<=n;i++) cin>>cnt[i]; sort(cnt,cnt+n+1); dp[0]=1.0; //不是0 matrix a={p,1-p,1,0}; //初始化矩阵,注意这个的推导过程 for(int i=1;i<=n;i++) //要1减去这个概率 因为这个概率是踩上雷的 dp[i]=dp[i-1]*(1-pow(a,cnt[i]-cnt[i-1]-1)); //注意不要丢括号 //注意是乘法不是加法 把每段概率乘起来 //注意是-1不是+1 //从上一个雷的下一个起 要走cnt[i]-cnt[i-1]-1步 才能到达下一个雷 //雷在1和5 从2走到5 需要3步 5-1-1=3 printf("%.7f\n",dp[n]); } return 0; }