zoukankan      html  css  js  c++  java
  • bzoj1415&洛谷P4206 [NOI2005]聪聪与可可

    概率与期望

    题意:
    每个时间单位,可可都会选择去相邻的景点(可能有多个)中的一个或停留在原景点不动。
    而去这些地方所发生的概率是相等的。
    当聪聪在景点 C 时,她会选一个更靠近 可可的景点,如果这样的景点有多个,她会选一个标号最小的景点。
    聪聪可以走一步或两步
    在每个时间单位,假设聪聪先走,可可后走。若聪聪和可可位 于同一个景点,则可可就被吃掉了。
    细节:
    猫可以走一步或两步;
    老鼠可以不动;
    猫必须走到离老鼠最近的点,如距离有相同,则选编号最小的点。

    分析:
    聪聪的移动位置是由可可的位置决定的

    #include<bits/stdc++.h>
    using namespace std;
    #define N 1005
    int to[N<<1],nex[N<<1],head[N],vis[N],dis[N][N],nx[N][N],tot=0,viss[N][N];
    double dp[N][N],du[N];
    void add(int a,int b)
    {
        to[++tot]=b; nex[tot]=head[a]; head[a]=tot;
    }
    queue<int >q;
    void spfa(int s)
    {
        memset(vis,0,sizeof(vis));
        q.push(s); dis[s][s]=0;
        while(!q.empty()){
            int u=q.front(); q.pop();
            if(vis[u]) continue;
            vis[u]=1;
            for(int i=head[u];i;i=nex[i]){
                int v=to[i];
                if(dis[s][u]+1<dis[s][v]){
                    dis[s][v]=dis[s][u]+1;
                    if(!vis[v]) q.push(v);
                }
            }
        }
    }
    double dpp(int u,int v)
    {
        //printf("%d %d
    ",u,v);
        if(viss[u][v]) return dp[u][v];
        if(u==v) return 0;
        int step1=nx[u][v];
        int step2=nx[step1][v];
        if(step1==v||step2==v) return 1;
        double k=du[v]+1;
        for(int i=head[v];i;i=nex[i]){
            int vv=to[i];
            dp[u][v]+=(dpp(step2,vv)+1.0)/k;
            //printf("%lf
    ",dp[u][v]);
        }
        dp[u][v]+=(dpp(step2,v)+1.0)/k*1.0;
        viss[u][v]=1;
        return dp[u][v];
    }
    int main()
    {
        int n,m,s,t,a,b;
        scanf("%d%d",&n,&m);
        scanf("%d%d",&s,&t);
        for(int i=1;i<=m;i++)
        scanf("%d%d",&a,&b),add(a,b),add(b,a),du[a]+=1.0,du[b]+=1.0;
        memset(dis,0x7f7f7f,sizeof(dis));
        memset(nx,0x7f7f7f,sizeof(nx));
        for(int i=1;i<=n;i++)
        spfa(i);
        for(int i=1;i<=n;i++)
         for(int j=head[i];j;j=nex[j]){
             int v=to[j];
             for(int k=1;k<=n;k++)
             if(dis[i][k]==dis[v][k]+1) nx[i][k]=min(nx[i][k],v);
        }
        /*for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++)
            printf("%d ",nx[i][j]);
            printf("
    ");
        }*/
        printf("%.3lf
    ",dpp(s,t));
    }


    要想统计答案 就必须要先计算出聪聪在i位置 可可在j位置 聪聪下一步的移动方案
    先用spfa对每一个点跑最短路 再统计聪聪下一个点应该走什么
    然后用记忆化搜索 如果走到了return 0 或者差一两步走到return 1
    否则就由大家都向前走的dp值推过来(猫肯定优选走两步)
    由于猫走的路线已经定了 枚举鼠走哪一个点 概率就是鼠原来所在的点的出度+1(可以停留)

  • 相关阅读:
    Altium Designer 20下载与安装教程
    推荐一些好用的Chrome插件
    记录生活——三款优秀云笔记的搭配使用
    Sublime Text3的安装以及python开发环境的搭建
    Altium Designer 只导出PCB元器件及标号的PDF文件的方法
    Altium Designer 编译原理图出现has no driving source警告解决办法
    Altium Designer 16 如何分别导出TOP层和BOTTOM层
    HTML学习记录和总结
    AD16/MDK5/CAD2019及2007/Dev-C++/Office2016专业版软件安装包
    Keil5调试过程中遇到的一些警告和错误
  • 原文地址:https://www.cnblogs.com/mowanying/p/11208405.html
Copyright © 2011-2022 走看看