题目链接:ZOJ 3640 Help Me Escape
概率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; }