题解:P9428 [蓝桥杯 2023 国 B] 逃跑
节选自:DP做题记录(三)(2025.4.5 - 2025.4.19)
这道题代码难度只有红,但思维难度直接把这道题提升到了绿。
我们设 \(dp_i\) 表示从第 \(i\) 个星球出发到根节点花费的最短时间的期望。
显然,如果一个星球 \(v\) 的父亲节点 \(u\) 是跳板星球,那么直接跳跃与往上走父亲是一样的效果,因此 \(dp_v = dp_u + 1\)。
那么如果 \(v\) 的父亲节点 \(u\) 不是跳板星球,那么此时直接跳跃肯定要更优秀一些。假设我们有至少一次跳成功了,那么这种情况的时间一定在 \(u\) 已经考虑过了(如果 \(v\) 跳成功,就钦定 \(u\) 这次一定跳成功;如果 \(v\) 失败了,就钦定 \(u\) 这次也失败了,这样一定能保证 \(u\) 和 \(v\) 到达根的时间一样)。唯一一种 \(u\) 无法复制的情况就是 \(v\) 每次跳跃都失败了,此时它就会多走一条 \(v\) 到 \(u\) 的边,概率是 \(p^{cnt}\)(\(cnt\) 是 \(v\) 到根路径上跳板星球的数量),因此对答案的贡献就会家上 \(p^{cnt}\),因此 \(dp_v = dp_u + p^{cnt}\),那么这道题就做完了。
点击查看代码
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 9;
struct Edge{
int v, nex;
} e[N << 1], e2[N];
int head[N], ecnt;
void addEdge(int u, int v){
e[++ecnt] = Edge{v, head[u]};
head[u] = ecnt;
}
int flag[N], n, m;
double dp[N], p, ans;
void dfs(int u, int fa, double pp){
if(flag[fa])
pp *= p;
if(u != 1){
if(flag[fa])
dp[u] = dp[fa] + 1;
else
dp[u] = dp[fa] + pp;
}
ans += dp[u];
for(int i = head[u]; i; i = e[i].nex){
int v = e[i].v;
if(v == fa)
continue;
dfs(v, u, pp);
}
pp /= p;
}
int main(){
scanf("%d%d%lf", &n, &m, &p);
for(int i = 1; i < n; i++){
int u, v;
scanf("%d%d", &u, &v);
addEdge(u, v);
addEdge(v, u);
}
for(int i = 1; i <= m; i++){
int u;
scanf("%d", &u);
flag[u] = true;
}
dfs(1, 0, 1);
printf("%.2lf", ans / n);
return 0;
}
本文来自博客园,作者:Orange_new,转载请注明原文链接:https://www.cnblogs.com/JPGOJCZX/p/18841176

浙公网安备 33010602011771号