概率dp。
开始没看明白题意,以为增加战斗力后还在这条path,后来发现不是这样的,而是增加战斗力后再随机选择path。
记忆化搜索很好想,递推的话开始没想明白从什么值开始往f循环,后来看了看别人写的代码自己又推了推才恍然大悟。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
const int MAX_N = 100 + 10;
const int MAX_M = 10000/* + 10000*/ + 10000 +500;
const double e = 1e-9;
double dp[MAX_M];
int c[MAX_N];
int n, f;
int get_t(int ci)
{
double ans = (1.0 + sqrt(5)) / 2.0 * ci * ci;
return (int)ans;
}
int main()
{
while(scanf("%d%d", &n, &f) != EOF)
{
int _max = 0;
for(int i = 1; i <= n; i++)
{
scanf("%d", &c[i]);
_max = max(_max, c[i]);
}
_max = max(_max << 1, f);
// _max = (_max << 1) + f;//左移操作符的优先级比较低
for(int i = _max; i >= f; i--)
{
dp[i] = 0;
for(int j = 1; j <= n; j++)
{
if(i > c[j])
dp[i] += (1.0 / n) * get_t(c[j]);
else
dp[i] += (1.0 / n) * (dp[i + c[j]] + 1);
}
}
printf("%.3lf\n", dp[f]);
}
return 0;
}
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
const int MAX_N = 100 + 10;
const int MAX_M = 10000 + 10000 + 500;
const double e = 1e-9;
double dp[MAX_M];
int c[MAX_N];
int n, f;
int get_t(int ci)
{
double ans = (1.0 + sqrt(5)) / 2.0 * ci * ci;
return (int)ans;
}
double solve(int f)
{
if(fabs(dp[f] + 1) > e)
return dp[f];
dp[f] = 0.0;
for(int i = 1; i <= n; i++)
{
if(f > c[i])
dp[f] += (1.0 / n) * get_t(c[i]);
else
dp[f] += (1.0 / n) * (solve(f + c[i]) + 1);
}
return dp[f];
}
int main()
{
while(scanf("%d%d", &n, &f) != EOF)
{
for(int i = 1; i <= n; i++)
scanf("%d", &c[i]);
memset(dp, -1, sizeof(dp));
printf("%.3lf\n", solve(f));
}
return 0;
}