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; }