题目是LightOJ - 1027 A Dangerous Maze的加强版,即多了一个条件,探险者能记住k个门,也就是在返回k次过程中这几个门不会再走一遍,接下来经过的每个门的概率就会变化,求出去的时间期望。
思维跟简单版的相似,每经过一个门出去期望都要考虑两种情况之和:一是能出去,二是返回再走一次才出去。
当时,(为返回的门数)
意味着每个返回都能记住,那么记完全部返回门时接下来走的都是出去门,
期望就是;
当时,
期望就是,(表示选择了k个返回门后,再从剩下的负值门里选择一个门的平均值,即返回门的平均值)
整理得:
然后从后往前推,,。
注意一点,求得期望是分数,给的值都是整数,涉及除法时要乘以1.0.
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
int a[105];
double dp[105];
int main(){
int T,t=1;scanf("%d",&T);
while(T--){
int n,k;scanf("%d%d",&n,&k);
int t_out=0,t_back=0;
int d_out=0,d_back=0;
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
if(a[i]>0){
t_out+=a[i];
d_out++;
}
else{
t_back+=abs(a[i]);
d_back++;
}
}
printf("Case %d: ",t++);
if(d_out==0){
printf("-1\n");
continue;
}
memset(dp,0,sizeof(dp));
if(k>=d_back){ //能记住所有的返回门
k=d_back;
dp[k]=1.0*t_out/d_out;
}
else dp[k]=1.0*(t_out+1.0*(d_back-k)*t_back/d_back)/(n-d_back);
if(k==0){
printf("%lf\n",dp[k]);
continue;
}
for(int i=k-1;i>=0;i--)
dp[i]=1.0*(t_out+1.0*(d_back-i)*(dp[i+1]+1.0*t_back/d_back))/(n-i);
printf("%lf\n",dp[0]);
}
return 0;
}