传送门
这是一道期望dp+二分
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j]表示到第i关,游戏计时器为j时完成游戏期望时间
d
p
[
i
]
[
j
]
=
m
i
n
(
d
p
[
1
]
[
0
]
,
p
[
i
]
∗
(
d
p
[
i
+
1
]
[
j
+
a
[
i
]
]
+
a
[
i
]
)
+
(
1
−
p
[
i
]
)
∗
(
d
p
[
i
+
1
]
[
j
+
b
[
i
]
]
+
b
[
i
]
)
)
dp[i][j]=min(dp[1][0],p[i]*(dp[i+1][j+a[i]]+a[i])+(1-p[i])*(dp[i+1][j+b[i]]+b[i]))
dp[i][j]=min(dp[1][0],p[i]∗(dp[i+1][j+a[i]]+a[i])+(1−p[i])∗(dp[i+1][j+b[i]]+b[i]))
答
案
就
是
d
p
[
1
]
[
0
]
答案就是dp[1][0]
答案就是dp[1][0]
二分
d
p
[
1
]
[
0
]
dp[1][0]
dp[1][0],然后跑dp
最终跑出的
d
p
[
1
]
[
0
]
dp[1][0]
dp[1][0]是否<
m
i
d
mid
mid
这题坑点:要卡卡常。。
Code:
#include <bits/stdc++.h>
#define maxn 55
#define maxm 5001
#define eps 1e-9
using namespace std;
double dp[maxn][maxm];
int n, m, a[maxn], b[maxn], p[maxn];
inline int read(){
int s = 0, w = 1;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') w = -1;
for (; isdigit(c); c = getchar()) s = (s << 1) + (s << 3) + (c ^ 48);
return s * w;
}
inline bool check(double k){
for (register int i = n; i; --i){
for (register int j = m + 1; j < maxm; ++j) dp[i + 1][j] = k;
for (register int j = 0; j <= m; ++j)
dp[i][j] = std::min((dp[i + 1][j + a[i]] + a[i]) * p[i] / 100 + (dp[i + 1][j + b[i]] + b[i]) * (100 - p[i]) / 100, k);
}
return dp[1][0] < k;
}
int main(){
n = read(), m = read();
for (register int i = 1; i <= n; ++i) a[i] = read(), b[i] = read(), p[i] = read();
double l = 0, r = 1e9;
while (r - l > eps){
double mid = (l + r) / 2;
(check(mid) ? r : l) = mid;
}
printf("%.10f\n", r);
return 0;
}

本文介绍了一种结合期望动态规划与二分查找算法解决特定游戏时间预测问题的方法。通过定义dp状态数组来表达到达不同游戏阶段的期望时间,并利用二分法优化搜索过程。
1558

被折叠的 条评论
为什么被折叠?



