bzoj1415 [Noi2005]聪聪和可可 (概率与期望)
2017-11-23 10:53
465 查看
Description
Input
数据的第1行为两个整数N和E,以空格分隔,分别表示森林中的景点数和连接相邻景点的路的条数。 第2行包含两个整数C和M,以空格分隔,分别表示初始时聪聪和可可所在的景点的编号。 接下来E行,每行两个整数,第i+2行的两个整数Ai和Bi表示景点Ai和景点Bi之间有一条路。 所有的路都是无向的,即:如果能从A走到B,就可以从B走到A。 输入保证任何两个景点之间不会有多于一条路直接相连,且聪聪和可可之间必有路直接或间接的相连。Output
输出1个实数,四舍五入保留三位小数,表示平均多少个时间单位后聪聪会把可可吃掉。Sample Input
【输入样例1】4 3
1 4
1 2
2 3
3 4
【输入样例2】
9 9
9 3
1 2
2 3
3 4
4 5
3 6
4 6
4 7
7 8
8 9
Sample Output
【输出样例1】1.500
【输出样例2】
2.167
HINT
【样例说明1】开始时,聪聪和可可分别在景点1和景点4。
第一个时刻,聪聪先走,她向更靠近可可(景点4)的景点走动,走到景点2,然后走到景点3;假定忽略走路所花时间。
可可后走,有两种可能:
第一种是走到景点3,这样聪聪和可可到达同一个景点,可可被吃掉,步数为1,概率为 。
第二种是停在景点4,不被吃掉。概率为 。
到第二个时刻,聪聪向更靠近可可(景点4)的景点走动,只需要走一步即和可可在同一景点。因此这种情况下聪聪会在两步吃掉可可。
所以平均的步数是1* +2* =1.5步。
对于所有的数据,1≤N,E≤1000。
对于50%的数据,1≤N≤50。
Source
[Submit][Status][Discuss]
分析:
首先聪聪的决策是有计划性的,而且与可可的位置有关
所以我们可以用n次bfs预处理出p[i][j]表示聪聪在i点可可在j点,聪聪下一步要到达的点
G[i][j]表示和i相连的编号第j大的结点
因为在多种方案的前提下,聪聪会优先选择编号小的点,
所以我们在bfs的时候就选择编号小的点优先入队,这样就可以保证最后记录的是最短路上的编号最小决策
f[i][j]表示聪聪在i,可可在j,聪聪捉到可可的期望时间
初始化:
i=j,f[i][j]=0
p[i][j]==j || p[p[i][j]][j]==j,f[i][j]=1
转移方程:
f[i][j]=( ( Σ{ f [ p[p[i][j]][j] ][ G[j][k] ] } + f [ p[p[i][j]][j] ][ j ] ) / (du[j]+1) )+1
因为我们已经与处理过能过直接抓到可可的状态所以需要上式转移的情况都是聪聪要走两步,可可有du+1种选择的情况
期望=总情况/情况总数
现在我们还有一个问题,就是我们要怎么转移呢
显然简单的从1到n这样的转移是没有前途的(原则:从稳定状态转移)
因为dp是在一个图上的,所以立马就想到了记忆化搜索
tip
注意数组类型,不要把int和double混用//这里写代码片 #include<cstdio> #include<cstring> #include<iostream> #include<cmath> #include<algorithm> using namespace std; const double INF=1e9; const int N=1005; int p ,n,m,du ; int G ,Q ,st ,tou,wei,s,t; double f ; bool vis ; void bfs(int s) //预处理 { tou=wei=0; for (int i=1;i<=st[s];i++) Q[++wei]=G[s][i],p[s][G[s][i]]=G[s][i]; p[s][s]=s; while (tou<wei) { int now=Q[++tou]; for (int i=1;i<=st[now];i++) { int v=G[now][i]; if (p[s][v]==-1) { p[s][v]=p[s][now]; Q[++wei]=v; } } } } double dfs(int i,int j) { if (vis[i][j]) return f[i][j]; vis[i][j]=1; double ans=0; for (int k=1;k<=st[j];k++) ans+=dfs(p[p[i][j]][j],G[j][k]); //聪聪一定会移动两步 ans+=dfs(p[p[i][j]][j],j); //可可不动 ans=ans/(double)(du[j]+1.0); ans=ans+1.0; return f[i][j]=ans; } void solve() { int i,j; memset(vis,0,sizeof(vis)); for (i=1;i<=n;i++) for (j=1;j<=n;j++) { f[i][j]=INF; if (j==p[i][j]||j==p[p[i][j]][j]) f[i][j]=1.0,vis[i][j]=1; //一次就可以到达 } for (int i=1;i<=n;i++) f[i][i]=0.0,vis[i][i]=1; dfs(s,t); printf("%.3lf",f[s][t]); } int main() { scanf("%d%d",&n,&m); scanf("%d%d",&s,&t); for (int i=1;i<=m;i++) { int u,w; scanf("%d%d",&u,&w); G[u][++st[u]]=w; G[w][++st[w]]=u; du[u]++; du[w]++; //度 } for (int i=1;i<=n;i++) sort(G[i]+1,G[i]+1+st[i]); //保证先到达编号小的节点 memset(p,-1,sizeof(p)); for (int i=1;i<=n;i++) bfs(i); //聪聪的位置 solve(); return 0; }
相关文章推荐
- bzoj1415 [Noi2005]聪聪和可可(期望概率DP+最短路)
- BZOJ 1415|NOI 2005|聪聪和可可|概率期望|动态规划
- 【BZOJ1415】[Noi2005]聪聪和可可 概率与期望
- bzoj1415 [Noi2005]聪聪和可可【概率dp 数学期望】
- [BZOJ1415][NOI2005]聪聪和可可-概率与期望
- BZOJ1415: [Noi2005]聪聪和可可 最短路 期望概率dp
- bzoj 1415: [Noi2005]聪聪和可可 (概率与期望)
- BZOJ 1415 NOI2005 聪聪和可可 期望DP+记忆化搜索 BZOJ200题达成&&NOI2005全AC达成
- [BZOJ 1415][NOI 2005]聪聪和可可(SPFA+概率DP)
- bzoj 1415 [Noi2005]聪聪和可可 概率dp
- [BZOJ]1415 [NOI2005] 聪聪与可可 期望 + 记忆化搜索
- BZOJ1415 [Noi2005]聪聪和可可 【SPFA + 期望dp记忆化搜索】
- 【BZOJ1415】【NOI2005】聪聪可可(期望dp、记忆化搜索)
- BZOJ 1415: [Noi2005]聪聪和可可( 最短路 + 期望dp )
- 1415: [Noi2005]聪聪和可可 概率与期望 记忆化搜索
- BZOJ 1415: [Noi2005]聪聪和可可 概率DP,记忆化搜索,BFS
- 【BZOJ1415】【Noi2005】聪聪和可可 概率DP 记忆化搜索
- BZOJ 1415: [Noi2005]聪聪和可可 [DP 概率]
- 【BZOJ】1415 [Noi2005]聪聪和可可 期望DP+记忆化搜索
- [BZOJ 1415][Noi2005]聪聪和可可:期望