题目
https://cn.vjudge.net/problem/HDU-4870
题意
一人用两个账号参加比赛,每次只会用分数较少的账号去参加。取胜加50分,落败扣100分但最多为0分。现在两个账号都为0分,给出取胜的概率p,问要参加多少场比赛能使其中一个账号到达1000分的期望。
思路
我们令dp【i】表示从(i - 1)* 50 到 i * 50 分的期望场数,(dp【1】表示 0 ~ 50 分的期望场数)。那么这时候分为赢和输两种情况,赢的话明显状态转移 dp【i】= 1 * p。输了的话就要从dp【i - 2】的位置从新起步,所以转移为dp【i】= (1 - p)* (1 + dp【i - 2】+ dp【i - 1】+ dp【i】)(1表示输了走的那一步)。那么总的转移也就是dp【i】= p + (1 - p)*(1 + dp【i - 2】+ dp【i - 1】+ dp【i】)。
#include <iostream> #include <cstring> #include <string> #include <algorithm> #include <cmath> #include <cstdio> #include <queue> #include <stack> #include <map> #define ull unsigned long long #define met(a, b) memset(a, b, sizeof(a)) #define lowbit(x) (x&(-x)) #define MID (l + r) / 2 #define ll long long using namespace std; const int maxn = 1e5 + 7; const ll mod = 1e6 + 3; const int inf = 0x3f3f3f3f; const ll INF = 0x3f3f3f3f3f3f3f3f; double dp[30]; int main() { double p; while(cin >> p) { double sum = 0;
//预处理 0 和 1 位置的dp值 dp[0] = 1/p; dp[1] = (1 + (1 - p) * dp[0]) / p; sum = dp[0] + dp[1]; for(int i = 2; i <= 19; i++) { dp[i] = (1 + (1 - p) * (dp[i-2] + dp[i-1])) / p; sum += dp[i]; } printf("%.6lf ", sum+sum-dp[19]); 最后其实两个账号一个为1000分,另一个是950分,所以减去dp【19】。 } return 0; }