zoukankan      html  css  js  c++  java
  • 【BZOJ】1415 [Noi2005]聪聪和可可 期望DP+记忆化搜索

    【题意】给定无向图,聪聪和可可各自位于一点,可可每单位时间随机向周围走一步或停留,聪聪每单位时间追两步(先走),问追到可可的期望时间。n<=1000。

    【算法】期望DP+记忆化搜索

    【题解】首先因为聪聪的步数大于可可,所以不可能出现循环,因此是DAG上的期望DP,用记忆化搜索解决。

    每个点bfs预处理p[x][y]表示x走向y的第一步位置,设f[x][y]表示聪聪在x可可在y追上的期望时间。

    $$f(x,y)=sum_{z}frac{f(g[g[i][j]]][j],z)}{out[x]+1}+1$$

    其中z是y的邻点和y自身。

    再判断一下一步到达,两步到达和重叠(可可随机到聪聪处)的情况即可。

    复杂度O(n^2)。

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    const int maxn=1010;
    struct edge{int from,v;}e[maxn*3];
    int n,m,a,b,ins[maxn],first[maxn],d[maxn],q[1010],p[maxn][maxn],tot;
    double f[maxn][maxn];
    void insert(int u,int v)
    {
        tot++;e[tot].v=v;e[tot].from=first[u];first[u]=tot;ins[u]++;
        tot++;e[tot].v=u;e[tot].from=first[v];first[v]=tot;ins[v]++;
    }
    double dp(int a,int b)
    {
        if(f[a][b])return f[a][b];
        if(a==b)return f[a][b]=0;
        if(p[a][b]==b||p[p[a][b]][b]==b)return f[a][b]=1;
        double ans=dp(p[p[a][b]][b],b);
        for(int i=first[b];i;i=e[i].from)
         ans+=dp(p[p[a][b]][b],e[i].v);
        return f[a][b]=ans/(1.0*ins[b]+1)+1;
    }
    void bfs(int x)
    {
        memset(d,-1,sizeof(d));
        int head=0,tail=0;d[x]=0;p[x][x]=0;
        for(int i=first[x];i;i=e[i].from)p[x][e[i].v]=e[i].v,d[e[i].v]=1,q[tail++]=e[i].v;
        while(head!=tail)
         {
             int y=q[head++];if(head>1000)head=0;int num=p[x][y];
             for(int i=first[y];i;i=e[i].from)
              if(d[e[i].v]==-1||((d[y]+1==d[e[i].v])&&num<p[x][e[i].v]))
               {
                   d[e[i].v]=d[y]+1;
                   p[x][e[i].v]=num;
                   q[tail++]=e[i].v;
                   if(tail>1000)tail=0;
               }
         }
    }
    int main()
    {
        scanf("%d%d%d%d",&n,&m,&a,&b);
        for(int i=1;i<=m;i++)
         {
             int u,v;
             scanf("%d%d",&u,&v);
             insert(u,v);
         }
        for(int i=1;i<=n;i++)bfs(i);
        printf("%.3lf",dp(a,b));
        return 0;
    }
    View Code
  • 相关阅读:
    OpenCV 创建Mat图像
    OpenCV Mat数据类型及位数总结
    OpenCV 使用at和ptr指针访问像素的区别
    OpenCV 16位深度图片显示并保存
    PyCharm 安装教程(Windows)
    Qt 安装图解(Windows平台)
    Qt 下载(多种下载通道+所有版本)
    QtCreator怎样编辑运行Python脚本
    Python 怎么运行代码
    Qt for Python 怎样搭建开发环境
  • 原文地址:https://www.cnblogs.com/onioncyc/p/6514466.html
Copyright © 2011-2022 走看看