首先肯定要先把所有的关卡打通后去找两星几率最大的关卡刷星(论打游戏经验的重要性)。
所以从两星几率小的关打起,记录当前拿到x个星星的几率和当前走过的期望步数,如果发现剩下的关必须全两星,就直接计算答案。
因为期望的线性,所以直接加起来不会有什么问题。
#include<bits/stdc++.h> #define double long double using namespace std; const int N = 4005; int n,m; double x[N],y[N]; int p[N]; bool cmp(int xx,int xy) { return y[xx]<y[xy]; } double b[N]; int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { scanf("%Lf%Lf",&x[i],&y[i]); x[i]/=1000;y[i]/=1000; } for(int i=1;i<=n;i++)p[i]=i; sort(p+1,p+n+1,cmp); b[0]=1; double ans=0; double now=1; for(int i=1;i<=n;i++) { int t=p[i]; if(m-(n-i+1)*2>=i-1) { double tmp=0; for(int j=i;j<=n;j++) { tmp+=1/y[p[j]]; } ans+=b[m-(n-i+1)*2]*tmp; now-=b[m-(n-i+1)*2]; b[m-(n-i+1)*2]=0; } ans+=now/(x[t]+y[t]); for(int j=2*n;j>=0;j--) { b[j]=0; if(j>=1)b[j]=b[j-1]*x[t]/(x[t]+y[t]); if(j>=2)b[j]+=b[j-2]*y[t]/(x[t]+y[t]); } } printf("%.10Lf ",ans); return 0; }