zoukankan      html  css  js  c++  java
  • bzoj1415 [Noi2005]聪聪和可可

    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$。这样大力转移就行了。

     1 //It is made by wfj_2048~
     2 #include <algorithm>
     3 #include <iostream>
     4 #include <complex>
     5 #include <cstring>
     6 #include <cstdlib>
     7 #include <cstdio>
     8 #include <vector>
     9 #include <cmath>
    10 #include <queue>
    11 #include <stack>
    12 #include <map>
    13 #include <set>
    14 #define inf (1<<30)
    15 #define eps (1e-9)
    16 #define N (1010)
    17 #define il inline
    18 #define RG register
    19 #define ll long long
    20 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
    21 
    22 using namespace std;
    23 
    24 struct edge{ int nt,to; }g[4*N];
    25 
    26 struct data{
    27     int d,x;
    28     bool operator < (const data &a) const{
    29     if (d==a.d) return x>a.x;
    30     return d>a.d;
    31     }
    32 };
    33 
    34 priority_queue <data> Q;
    35 
    36 int head[N],vis[N],fa[N],d[N],p[N][N],vi[N][N],n,e,c,m,num,cnt;
    37 long double f[N][N];
    38 
    39 il int gi(){
    40     RG int x=0,q=1; RG char ch=getchar();
    41     while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
    42     if (ch=='-') q=-1,ch=getchar();
    43     while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar();
    44     return q*x;
    45 }
    46 
    47 il void insert(RG int from,RG int to){
    48     g[++num]=(edge){head[from],to},head[from]=num; return;
    49 }
    50 
    51 il void bfs(RG int S){
    52     Q.push((data){0,S}),vis[S]=++cnt;
    53     while (!Q.empty()){
    54     RG data h=Q.top(); RG int x=h.x,v; Q.pop();
    55     for (RG int i=head[x];i;i=g[i].nt){
    56         v=g[i].to; if (vis[v]==cnt) continue;
    57         if (x==S) p[v][S]=x; else p[v][S]=fa[x];
    58         fa[v]=x,vis[v]=cnt,Q.push((data){h.d+1,v});
    59     }
    60     }
    61     return;
    62 }
    63 
    64 il long double dfs(RG int x,RG int y){
    65     if (x==y) return 0.0;
    66     if (p[x][y]==y) return 1.0;
    67     if (vi[x][y]) return f[x][y];
    68     vi[x][y]=1,f[x][y]=0.0; RG int v;
    69     for (RG int i=head[y];i;i=g[i].nt)
    70     v=g[i].to,f[x][y]+=dfs(p[x][y],v)+1.0;
    71     f[x][y]+=dfs(p[x][y],y)+1.0,f[x][y]/=(1.0*(d[y]+1));
    72     return f[x][y];
    73 }
    74 
    75 il void work(){
    76     n=gi(),e=gi(),c=gi(),m=gi();
    77     for (RG int i=1,u,v;i<=e;++i){
    78     u=gi(),v=gi(),d[u]++,d[v]++;
    79     insert(u,v),insert(v,u);
    80     }
    81     for (RG int i=1;i<=n;++i) bfs(i);
    82     printf("%0.3Lf
    ",dfs(c,m)); return;
    83 }
    84 
    85 int main(){
    86     File("1415");
    87     work();
    88     return 0;
    89 }
  • 相关阅读:
    42 最大子数组Ⅱ
    笔试之const问题
    笔试中sizeof求字节数的问题
    40 用栈实现队列
    38 搜索二维矩阵Ⅱ
    25.Remove Nth Node From End of List(删除链表的倒数第n个节点)
    29.最小的K个数
    28.数组中出现次数超过一半的数字
    27.字符串的排列
    26.二叉搜索树与双向链表
  • 原文地址:https://www.cnblogs.com/wfj2048/p/6689383.html
Copyright © 2011-2022 走看看