前言:学长讲的太神了;自己还能推出来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. kubernetes系列(十四) - 存储之PersistentVolume

    1. PersistentVolume(PV)简介 1.1 为什么需要Persistent Volume(PV) 1.2 PersistentVolume(PV)和Volume的区别 1.3 PV和P ...

  2. 主题博客添加 h5 贴边音乐插件

    前言: 前几日,在逛微博的时候,发现微博主页的左下角有一个贴边的音乐小插件,我顿时就想在自己博客上也弄一个玩玩.当时就想把微博那个移植过来,首先我用谷歌浏览器F12 查看页面源码,和检查元素代码,发现 ...

  3. 机器学习实战基础(十):sklearn中的数据预处理和特征工程(三) 数据预处理 Preprocessing & Impute 之 缺失值

    缺失值 机器学习和数据挖掘中所使用的数据,永远不可能是完美的.很多特征,对于分析和建模来说意义非凡,但对于实际收集数据的人却不是如此,因此数据挖掘之中,常常会有重要的字段缺失值很多,但又不能舍弃字段的 ...

  4. saver 的保存与恢复

    模型保存,先要创建一个Saver对象:saver=tf.train.Saver(), max_to_keep 是用来设置保存模型的个数,默认为5,即保存最近的五个模型,saver=tf.train.S ...

  5. java大数据最全课程学习笔记(1)--Hadoop简介和安装及伪分布式

    Hadoop简介和安装及伪分布式 大数据概念 大数据概论 大数据(Big Data): 指无法在一定时间范围内用常规软件工具进行捕捉,管理和处理的数据集合,是需要新处理模式才能具有更强的决策力,洞察发 ...

  6. Python读取文件基本方法

    在日常开发过程中,经常遇到需要读取配置文件,这边就涉及到一个文本读取的方法. 这篇文章主要以Python读取文本的基础方法为本,添加读取整篇文本返回字符串,读取键值对返回字典,以及读取各个项返回列表的 ...

  7. 一张PDF了解JDK10 GC调优秘籍-附PDF下载

    目录 简介 Java参数类型 Large Pages JIT调优 总结 简介 今天我们讲讲JDK10中的JVM GC调优参数,JDK10中JVM的参数总共有1957个,其中正式的参数有658个. 其实 ...

  8. bzoj3446[Usaco2014 Feb]Cow Decathlon*

    bzoj3446[Usaco2014 Feb]Cow Decathlon 题意: FJ有n头奶牛.FJ提供n种不同的技能供奶牛们学习,每头奶牛只能学习一门技能,每门技能都要有奶牛学习. 第i头奶牛学习 ...

  9. Python Ethical Hacking - BACKDOORS(8)

    Cross-platform hacking All programs we wrote are pure python programs They do not rely on OS-specifi ...

  10. 并发编程AQS----共享锁

    Semaphore Semaphore 字面意思是信号量的意思,它的作用是控制访问特定资源的线程数目.应用场景:资源访问,服务限流. Semaphore 实现AbstractQueuedSynchro ...