题意
某人被抓进了洞穴,要想办法逃出来。洞穴有N个出口,每个洞口有一个怪,每个怪有战斗力C[i]。
这个人的初始战斗力是f。每天他会选择一个出口逃走。
如果他的战斗力f>C[i],那么他可以打败怪物并花费t[i] = (1.0+sqrt(5.0))*0.5*C[i]*C[i](取整)天逃出去。
否则他会修炼一天,战斗力提升f = f+c[i]。第二天再随机选择一个出口。
此人一定能逃出去,问他逃出去的天数期望
题解
如果设DP[x]是战斗力为x逃出去的天数期望
如果当前的战斗力高于C[i]那么DP[x] += t[i]/n。
否则DP[x] += (DP[x+C[i]] + 1)/ n
那么两种方法,一种是dfs记忆化搜索,一种是递推(但是要逆向推倒)
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 110;
int c[maxn];
int t[maxn];
double dp[100000];
int n;
double dfs(int x)
{
if(dp[x]>0) return dp[x];
for(int i = 1; i <= n; i++)
{
if(x > c[i])
dp[x]+=(double)t[i]/n;
else
dp[x]+=(dfs(x+c[i])+1.0)/n;
}
return dp[x];
}
int main()
{
double f;
while(~scanf("%d%lf", &n, &f))
{
memset(dp, 0, sizeof(dp));
double p = (1.0+sqrt(5.0))*0.5;
for(int i = 1; i <= n; i++)
{
scanf("%d", &c[i]);
t[i] = p*c[i]*c[i];
}
double ans = dfs(f);
printf("%.3lf\n", ans);
}
return 0;
}
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 110;
int c[maxn];
int t[maxn];
double dp[100000];
int n, f;
int main()
{
while(~scanf("%d%d", &n, &f))
{
memset(dp, 0, sizeof(dp));
double p = (1.0+sqrt(5.0))*0.5;
int Max = -1;
int m;
for(int i = 1; i <= n; i++)
{
scanf("%d", &c[i]);
Max = max(c[i], Max);
t[i] = p*c[i]*c[i];
cout << i << " " << t[i] << endl;
}
m = 2*Max;
if(f > Max) {
m = f;
}
for (int i=m;i>=f;--i)
for (int j=1;j<=n;++j)
if (i>c[j]) dp[i]+=t[j]/(double)n;
else dp[i]+=(dp[i+c[j]]+1)/(double)n;
printf("%.3lf\n", dp[f]);
}
return 0;
}