bzoj1415 [Noi2005]聪聪和可可
2017-04-10 15:48
239 查看
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。
正解:概率dp(记忆化搜索)。
这题还是比较简单的,不过有坑啊。。如果两个点与可可所在点一样近,那么选标号小的。。
首先我们可以$bfs$预处理出一个数组$p[x][y]$表示聪聪在$x$点,可可在$y$点时聪聪下$1$秒会到哪个点。因为有标号限制,所以我们要用一个堆来维护队列,我偷懒于是写了优先队列。预处理复杂度是$O(n^{2}logn)$的。
接下来就是记忆化搜索了,设$f[x][y]$表示聪聪在$x$点,可可在$y$点的期望时间,那么$f[x][y]=(\sum(f[p[x][y]][v]+1)+f[p[x][y]][y]+1)/(d[y]+1)$,其中$v$表示与$y$相邻的点,$d[y]$表示$y$的度数。注意,如果$x=y$,那么$f[x][y]=0$;如果$p[x][y]=y$,那么$f[x][y]=1$。这样大力转移就行了。
//It is made by wfj_2048~ #include <algorithm> #include <iostream> #include <complex> #include <cstring> #include <cstdlib> #include <cstdio> #include <vector> #include <cmath> #include <queue> #include <stack> #include <map> #include <set> #define inf (1<<30) #define eps (1e-9) #define N (1010) #define il inline #define RG register #define ll long long #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout) using namespace std; struct edge{ int nt,to; }g[4*N]; struct data{ int d,x; bool operator < (const data &a) const{ if (d==a.d) return x>a.x; return d>a.d; } }; priority_queue <data> Q; int head ,vis ,fa ,d ,p ,vi ,n,e,c,m,num,cnt; long double f ; il int gi(){ RG int x=0,q=1; RG char ch=getchar(); while ((ch<'0' || ch>'9') && ch!='-') ch=getchar(); if (ch=='-') q=-1,ch=getchar(); while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); return q*x; } il void insert(RG int from,RG int to){ g[++num]=(edge){head[from],to},head[from]=num; return; } il void bfs(RG int S){ Q.push((data){0,S}),vis[S]=++cnt; while (!Q.empty()){ RG data h=Q.top(); RG int x=h.x,v; Q.pop(); for (RG int i=head[x];i;i=g[i].nt){ v=g[i].to; if (vis[v]==cnt) continue; if (x==S) p[v][S]=x; else p[v][S]=fa[x]; fa[v]=x,vis[v]=cnt,Q.push((data){h.d+1,v}); } } return; } il long double dfs(RG int x,RG int y){ if (x==y) return 0.0; if (p[x][y]==y) return 1.0; if (vi[x][y]) return f[x][y]; vi[x][y]=1,f[x][y]=0.0; RG int v; for (RG int i=head[y];i;i=g[i].nt) v=g[i].to,f[x][y]+=dfs(p[x][y],v)+1.0; f[x][y]+=dfs(p[x][y],y)+1.0,f[x][y]/=(1.0*(d[y]+1)); return f[x][y]; } il void work(){ n=gi(),e=gi(),c=gi(),m=gi(); for (RG int i=1,u,v;i<=e;++i){ u=gi(),v=gi(),d[u]++,d[v]++; insert(u,v),insert(v,u); } for (RG int i=1;i<=n;++i) bfs(i); printf("%0.3Lf\n",dfs(c,m)); return; } int main(){ File("1415"); work(); return 0; }
相关文章推荐
- [bzoj1415][Noi2005]聪聪和可可 期望DP+记忆化搜索 & bzoj100题
- bzoj 1415 [Noi2005]聪聪和可可 概率dp
- bzoj1415 [Noi2005]聪聪和可可 (概率与期望)
- bzoj 1415: [Noi2005]聪聪和可可
- BZOJ 1415 [Noi2005]聪聪和可可【概率dp】
- bzoj1415 [Noi2005]聪聪和可可【概率dp 数学期望】
- [BZOJ1415][NOI2005]聪聪和可可-概率与期望
- [NOI2005]BZOJ1415 聪聪和可可
- BZOJ 1415: [Noi2005]聪聪和可可
- 【BZOJ 1415】 [Noi2005]聪聪和可可
- Bzoj1415 [Noi2005]聪聪和可可
- [BZOJ 1415][NOI 2005]聪聪和可可(SPFA+概率DP)
- BZOJ 1415|NOI 2005|聪聪和可可|概率期望|动态规划
- 【BZOJ1415】[Noi2005]聪聪和可可 概率与期望
- BZOJ 1415: [Noi2005]聪聪和可可
- 【BZOJ】【1415】【NOI2005】聪聪和可可
- bzoj 1415: [Noi2005]聪聪和可可【期望dp+bfs】
- 【BZOJ1415】【NOI2005】聪聪与可可(期望dp+预处理)
- [BZOJ]1415 [NOI2005] 聪聪与可可 期望 + 记忆化搜索
- Bzoj1415: [Noi2005]聪聪和可可