zoukankan      html  css  js  c++  java
  • 洛谷4206/NOI2005T4 聪聪和可可 期望DP+记忆化搜索

    题意:给出n个点m条边的无向图,两个主角聪聪和可可开始分别在S点和T点。聪聪想吃掉可可,每次由匆匆先行动后来可可行动。聪聪的行动是选他到可可的最短路上的点走最多两步(如果最短路有几条就选编号最小的走),可可的行动是等概率选择一个出点或者不动。问聪聪吃掉可可的期望行动次数。

    解法:这道题还是蛮有意思的。

    首先我们必须得先注意到聪聪得行动是“智能”的不随机,这样我们不能计算的时候再考虑,我们必须得先预处理nxt[x][y]代表若聪聪在x点可可在y点下一步聪聪会走那个点(根据定义就是x到y最短路的编号最小点)预处理这个我们可以做n次最短路,方法是:当在x点能更新到某个点y的最短路的时候,随便把这个nxt[st][y]与nxt[st][x]取一个最小值。

    预处理之后我们就可以开始计算答案了。

    因为在图上dp,没有比较显然的阶段所以我们使用记忆化搜素。dp[x][y]代表聪聪在x点,可可在y点的期望答案。分3种情况转移:

    ①x==y  , dp[x][y]=0

    ②x能通过1/2步走到y,dp[x][y]=1

    ③否则  to=x向y走两步走到的点,dp[x][y]=(sigma(dp[to][z])+dp[to][y]) / (du[y]+1) + 1 ;   (z表示y出点,du[y]表示y出度),应该比较好理解就是聪聪先走两部,然后可可随机走一步(或者停)的期望相加。

    这里提一点,为什么在这个图上能走dp,dp状态之间不会有环吗?因为其实聪聪的行动是十分“智能”的,这就导致了dp状态之间其实不会有环,会有先后顺序。

    代码如下:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int N=1e3+10;
     4 const int INF=0x3f3f3f3f;
     5 int n,m,s,t;
     6 vector<int> G[N];
     7 double dp[N][N]; 
     8 bool vis[N][N];
     9 
    10 int nxt[N][N];
    11 queue<int> q;
    12 int dis[N]; bool inq[N];
    13 void spfa(int st) {
    14     for (int i=1;i<=n;i++) dis[i]=INF,inq[i]=0;
    15     dis[st]=0;
    16     for (int i=0;i<G[st].size();i++) {
    17         int y=G[st][i];
    18         dis[y]=1; q.push(y); inq[y]=1;
    19         nxt[st][y]=min(nxt[st][y],y);
    20     }
    21     while (!q.empty()) {
    22         int x=q.front(); q.pop();
    23         for (int i=0;i<G[x].size();i++) {
    24             int y=G[x][i];
    25             if (dis[y]>=dis[x]+1) {
    26                 dis[y]=dis[x]+1;
    27                 nxt[st][y]=min(nxt[st][y],nxt[st][x]);
    28                 if (!inq[y]) q.push(y),inq[y]=1;
    29             }
    30         }
    31         inq[x]=0;
    32     } 
    33 }
    34 
    35 double dfs(int s,int t) {
    36     if (vis[s][t]) return dp[s][t];
    37     int to=nxt[nxt[s][t]][t];
    38     vis[s][t]=1;
    39     if (s==t) return dp[s][t]=0.0;
    40     if (to==t) return dp[s][t]=1.0;
    41     dp[s][t]+=dfs(to,t);
    42     for (int i=0;i<G[t].size();i++)
    43         dp[s][t]+=dfs(to,G[t][i]);
    44     dp[s][t]/=(double)(G[t].size()+1);
    45     dp[s][t]+=1.0;
    46     return dp[s][t];
    47 }
    48 
    49 int main()
    50 {
    51     cin>>n>>m>>s>>t;
    52     for (int i=1;i<=m;i++) {
    53         int x,y; scanf("%d%d",&x,&y);
    54         G[x].push_back(y); 
    55         G[y].push_back(x);
    56     }
    57     
    58     memset(nxt,0x3f,sizeof(nxt));
    59     for (int i=1;i<=n;i++) nxt[i][i]=i;
    60     for (int i=1;i<=n;i++) spfa(i);
    61     
    62     memset(dp,0,sizeof(dp));
    63     memset(vis,0,sizeof(vis));
    64     printf("%.3lf
    ",dfs(s,t));
    65     return 0;
    66 }
  • 相关阅读:
    paip.关于动画特效原理 html js 框架总结
    paip.utf-8,unicode编码的本质输出unicode文件原理 python
    paip.多维理念 输入法的外码输入理论跟文字输出类型精髓
    paip.前端加载时间分析之道优化最佳实践
    paip.输入法编程--英文ati化By音标原理与中文atiEn处理流程 python 代码为例
    paip.导入数据英文音标到数据库mysql为空的问题之道解决原理
    paip.元数据驱动的转换-读取文件行到个list理念 uapi java php python总结
    paip.python3 的类使用跟python2 的不同之处
    paip.日志中文编码原理问题本质解决python
    paip.性能跟踪profile原理与架构与本质-- python扫带java php
  • 原文地址:https://www.cnblogs.com/clno1/p/11636128.html
Copyright © 2011-2022 走看看