前言:学长讲的太神了;自己还能推出来DP式子,挺开心。

--------------------------

题目链接

题目大意:给定一张含有$n$个结点$m$条边的无向连通图。现在聪聪在点$s$,可可在点$t$。每秒钟可可能等概率走向相邻的结点或原地不动,而聪聪总是向更靠近可可的地方沿最短路走两步(如果走一步就能找到可可就不往下走了)。问聪聪找到可可的时间的期望。$n,m\leq 1000$

----------------------

我们首先解决第一个限制条件:沿最短路走。

假设聪聪目前在点$i$,可可目前在点$j$,聪聪下一步的走位是$next[i][j]$。

看到数据范围,我们可以暴力把每个点的单源最短路径求出来,然后枚举距离点$i$距离为$1$的点$k$。如果$dis[i][j]-1==dis[k][j]$,那么$next[i][j]=k$。

然后进行期望DP。这里我们采用记忆化搜索。设$f[i][j]$表示目前聪聪在点$i$,可可在点$j$时的期望。设点的出度为$du[]$。然后分类讨论:

  1.如果$i$和$j$同点,那么$f[i][j]=0$。

  2.如果聪聪能够走一步或两步到达点$j$,那么$f[i][j]=1$。

  3.如果可可呆在原地不动,那么对答案的贡献有$(f[next[next[i][j]][j]][j]+1)*\frac{1}{du[j]+1}$。(一共有$du[j]+1$种走法,包含原地不动)

  4.如果可可走向相邻的点,那么对答案的贡献有$\sum (f[next[next[i][j]][j]][to]+1)*\frac{1}{du[j]+1}$。(枚举$to$)

所以总的DP方程为$f[i][j]=\frac{f[next[next[i][j]][j]][j]+\sum f[next[next[i][j]][j]][to]}{du[j]+1}+1$

最后输出$dfs(s,t)$即可。时间复杂度$O(n^2)$。

代码:

#include<bits/stdc++.h>
using namespace std;
int dis[][],next[][],du[],vis[];
int n,m,s,t,visit[][];
double f[][];
int head[],cnt;
struct node
{
int next,to,dis;
}edge[];
inline int read()
{
int x=,f=;char ch=getchar();
while(!isdigit(ch)){if (ch=='-') f=-;ch=getchar();}
while(isdigit(ch)){x=x*+ch-'';ch=getchar();}
return x*f;
}
inline void add(int from,int to,int dis)
{
edge[++cnt].next=head[from];
edge[cnt].to=to;
edge[cnt].dis=dis;
head[from]=cnt;
}
inline void spfa(int x)
{
queue<int> q;
dis[x][x]=;vis[x]=;q.push(x);
while(!q.empty())
{
int now=q.front();q.pop();vis[now]=;
for (int i=head[now];i;i=edge[i].next)
{
int to=edge[i].to;
if (dis[x][to]>dis[x][now]+edge[i].dis)
{
dis[x][to]=dis[x][now]+edge[i].dis;
if (!vis[to]) q.push(to),vis[to]=;
}
}
}
}
double dfs(int u,int v)
{
if (visit[u][v]) return f[u][v];
if (u==v) return ;
int fir=next[u][v];
int sec=next[fir][v];
if (fir==v||sec==v) return ;
f[u][v]=;
for (int i=head[v];i;i=edge[i].next)
{
int to=edge[i].to;
f[u][v]+=dfs(sec,to)/(double)(du[v]+);
}
f[u][v]+=dfs(sec,v)/(double)(du[v]+);
visit[u][v]=;
return f[u][v];
}
int main()
{
n=read(),m=read(),s=read(),t=read();
for (int i=;i<=m;i++)
{
int x=read(),y=read();
add(x,y,);
add(y,x,);
du[x]++,du[y]++;
}
for (int i=;i<=n;i++)
for (int j=;j<=n;j++) dis[i][j]=next[i][j]=0x3f3f3f3f;
for (int i=;i<=n;i++) spfa(i);
for (int i=;i<=n;i++)
for (int j=head[i];j;j=edge[j].next)
{
int to=edge[j].to;
for (int k=;k<=n;k++)
if (dis[i][k]-==dis[to][k]) next[i][k]=min(next[i][k],to);
}
printf("%.3lf",dfs(s,t));
return ;
}

【NOI2005】聪聪与可可 题解(最短路+期望DP)的更多相关文章

  1. BZOJ 1415: [Noi2005]聪聪和可可( 最短路 + 期望dp )

    用最短路暴力搞出s(i, j)表示聪聪在i, 可可在j处时聪聪会走的路线. 然后就可以dp了, dp(i, j) = [ dp(s(s(i,j), j), j) + Σdp(s(s(i,j), j), ...

  2. BZOJ1415[Noi2005]聪聪和可可——记忆化搜索+期望dp

    题目描述 输入 数据的第1行为两个整数N和E,以空格分隔,分别表示森林中的景点数和连接相邻景点的路的条数. 第2行包含两个整数C和M,以空格分隔,分别表示初始时聪聪和可可所在的景点的编号. 接下来E行 ...

  3. BZOJ5197:[CERC2017]Gambling Guide(最短路,期望DP)

    Description 给定一张n个点,m条双向边的无向图. 你要从1号点走到n号点.当你位于x点时,你需要花1元钱,等概率随机地买到与x相邻的一个点的票,只有通过票才能走到其它点. 每当完成一次交易 ...

  4. 【BZOJ】1415: [Noi2005]聪聪和可可【期望】【最短路】【记忆化搜索】

    1415: [Noi2005]聪聪和可可 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2335  Solved: 1373[Submit][Stat ...

  5. 洛谷 P4206 [NOI2005]聪聪与可可 题解

    题面 输入 数据的第1行为两个整数N和E,以空格分隔,分别表示森林中的景点数和连接相邻景点的路的条数. 第2行包含两个整数C和M,以空格分隔,分别表示初始时聪聪和可可所在的景点的编号. 接下来E行,每 ...

  6. 【BZOJ1415】【NOI2005】聪聪和可可(动态规划,数学期望)

    [BZOJ1415][NOI2005]聪聪和可可(动态规划,数学期望) 题面 BZOJ 题解 先预处理出当可可在某个点,聪聪在某个点时 聪聪会往哪里走 然后记忆化搜索一下就好了 #include< ...

  7. 【bzoj1415】[Noi2005]聪聪和可可 期望记忆化搜索

    题目描述 输入 数据的第1行为两个整数N和E,以空格分隔,分别表示森林中的景点数和连接相邻景点的路的条数. 第2行包含两个整数C和M,以空格分隔,分别表示初始时聪聪和可可所在的景点的编号. 接下来E行 ...

  8. BZOJ1415 [Noi2005]聪聪和可可 【SPFA + 期望dp记忆化搜索】

    题目 输入格式 数据的第1行为两个整数N和E,以空格分隔,分别表示森林中的景点数和连接相邻景点的路的条数. 第2行包含两个整数C和M,以空格分隔,分别表示初始时聪聪和可可所在的景点的编号. 接下来E行 ...

  9. BZOJ_1415_[Noi2005]聪聪和可可_概率DP+bfs

    BZOJ_1415_[Noi2005]聪聪和可可_概率DP+bfs Description Input 数据的第1行为两个整数N和E,以空格分隔,分别表示森林中的景点数和连接相邻景点的路的条数. 第2 ...

随机推荐

  1. Python 图像处理 OpenCV (13): Scharr 算子和 LOG 算子边缘检测技术

    前文传送门: 「Python 图像处理 OpenCV (1):入门」 「Python 图像处理 OpenCV (2):像素处理与 Numpy 操作以及 Matplotlib 显示图像」 「Python ...

  2. vs2019使用github

    本人操作系统win10 第一步,下载vs github插件 直接看图 下载完成后,需要关闭所有vs2019窗口,之后会弹出下面的窗口,点击modify,完成之后,重新打开vs就安装好了 下面就可以在v ...

  3. 02 drf源码剖析之快速了解drf

    02 drf源码剖析之快速了解drf 目录 02 drf源码剖析之快速了解drf 1. 什么是drf 2. 安装 3. 使用 3. DRF的应用场景 1. 什么是drf drf是一个基于django开 ...

  4. bzoj3043IncDec Sequence*

    bzoj3043IncDec Sequence 题意: n个数,每次可以将区间l到r里的数+1或-1,问将它们变成同个数的最小操作次数和保证最小操作次数前提下有多少中可能.n≤100000. 题解: ...

  5. 主席树铺垫——总区间第k小

    题目描述(口糊) 先给定一个长度为n的数列,然后给m次操作,每次输入b,求第b小的数. 样例输入 5 7 4 10 9 23 5 1 2 3 4 5 样例输出 4 7 9 10 23 数据范围及温馨提 ...

  6. ModuleNotFoundError: No module named 'phkit.pinyin'

    1 产生背景 在mac系统本地使用正常,在linux系统上phkit包缺少相应的python文件 2 解决方案 自己想出来,手动上传本地相关python代码到linux服务器 3 解决过程 首先通过项 ...

  7. vue : rem自适应的应用

    我们知道,rem是一个css单位,指的是HTML根节点的字体大小. MDN:css单位 而我们在用rem布局的时候必然会遇到一个问题:我们需要根据用户的屏幕大小去计算rem. 以下是代码. (在VUE ...

  8. layui 魔改:富文本编辑器添加上传视频功能

    甲方又整新需求了:富文本编辑器需要可以传视频. layui本身的富文本编辑器没有传视频的功能,所以,又到了咱们魔改的时候了. 友情提醒,富文本编辑器 layedit 只有layui的V1版有,V2版没 ...

  9. 微软如何绑定二次验证码_虚拟MFA_两步验证_身份验证?

    1.登陆Microsoft账户,找到二次验证绑定界面 进入Microsoft,点右上角用户头像进行登陆.之后点“安全性”. 之后点击[更多安全选项] 找到“身份验证应用”(注意不是“双重验证”).点击 ...

  10. presto和hive日期函数对比

    时间格式转换 日期格式→Unix时间戳 转10位Unix时间戳 数据:2020-07-23 15:01:13 Presto:select to_unixtime(cast('2020-07-23 15 ...