聪聪和可可 HYSBZ - 1415(概率 + spfa + 记忆化dp)

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

解析:

  设f[i][j]为聪聪从i到j下一步 应该走的结点

  想一下,i 到 j 的期望步数,是不是sum(f[f[i][j]][t] * (out[j] + 1)) + 1   t为j的下一个结点 或者 j本身 意思是可可下一步到达的结点

  out[j]为j的出度 + 1 后 意味着可可有下一步有out[j] + 1种选择  那么每种选择的概率即为 1 / (out[j] + 1)

  那么这个公式的意思为 i 到 j 的期望步数 等于 i的所有的子结点 到 j的 期望步数乘相应的概率   最后的+1 是从i到子结点需要1步

  那么层层搜一下就好了

  f数组用n次spfa即可 不要忽略了聪聪每一步都会走标号最小的结点

#include <iostream>
#include <cstdio>
#include <sstream>
#include <cstring>
#include <map>
#include <cctype>
#include <set>
#include <vector>
#include <stack>
#include <queue>
#include <algorithm>
#include <cmath>
#include <bitset>
#define rap(i, a, n) for(int i=a; i<=n; i++)
#define rep(i, a, n) for(int i=a; i<n; i++)
#define lap(i, a, n) for(int i=n; i>=a; i--)
#define lep(i, a, n) for(int i=n; i>a; i--)
#define rd(a) scanf("%d", &a)
#define rlld(a) scanf("%lld", &a)
#define rc(a) scanf("%c", &a)
#define rs(a) scanf("%s", a)
#define pd(a) printf("%d\n", a);
#define plld(a) printf("%lld\n", a);
#define pc(a) printf("%c\n", a);
#define ps(a) printf("%s\n", a);
#define MOD 2018
#define LL long long
#define ULL unsigned long long
#define Pair pair<int, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define _  ios_base::sync_with_stdio(0),cin.tie(0)
//freopen("1.txt", "r", stdin);
using namespace std;
const int maxn = 1010, INF = 0x7fffffff, LL_INF = 0x7fffffffffffffff;
int n, m, ss, tt, cnt;
int head[maxn], f[maxn][maxn], vis[maxn], pre[maxn], d[maxn], out[maxn];
double p[maxn][maxn];
struct node
{
    int v, next;
}Node[maxn << 1];

void add_(int u, int v)
{
    out[u]++;
    Node[cnt].v = v;
    Node[cnt].next = head[u];
    head[u] = cnt++;
}

void add(int u, int v)
{
    add_(u, v);
    add_(v, u);
}

void spfa(int s)
{
    queue<int> Q;
    for(int i = 1; i <= n; i++) d[i] = INF;
    d[s] = 0;
    mem(vis, 0);
    Q.push(s); vis[s] = 1;
    while(!Q.empty())
    {
        int u = Q.front(); Q.pop();
        vis[u] = 0;
        for(int i = head[u]; i != -1; i = Node[i].next)
        {
            node e = Node[i];
            if(d[e.v] > d[u] + 1 || d[e.v] == d[u] + 1 && u < pre[e.v])
            {
                d[e.v] = d[u] + 1;
                pre[e.v] = u;
                if(!vis[e.v])
                {
                    vis[e.v] = 1;
                    Q.push(e.v);
                }
            }
        }
    }
    for(int i = 1; i <= n; i++)
        if(i != s)
            f[i][s] = pre[i];
}

double m_dfs(int u, int t)
{
    if(u == t) return p[u][t] = 0;
    if(f[u][t] == t) return p[u][t] = 1;
    if(f[f[u][t]][t] == t) return p[u][t] = 1;
    if(p[u][t] >= -1e-7) return p[u][t];
    int nxt = f[f[u][t]][t];
    double res = 1;
    for(int i = head[t]; i != -1; i = Node[i].next)
    {
        node e = Node[i];
        res += m_dfs(nxt, e.v) /(double) (out[t] + 1);
    }
    res += m_dfs(nxt, t) /(double) (out[t] + 1);
    return p[u][t] = res;
}

int main()
{
    mem(head, -1);
    int u, v;
    cin >> n >> m >> ss >> tt;
    rap(i, 1, m)
    {
        cin >> u >> v;
        add(u, v);
    }
    for(int i = 1; i <= n; i++)
        spfa(i);
    mem(p, -1);
    printf("%.3f\n", m_dfs(ss, tt));

    return 0;
}

题目总结:

  聪聪会走最短路,那么要想到最短路算法,因为每一步都是不确定的, 所以我们可以事先求出所有的每两点的情况,

  对期望分布列不明确,没有想到具体的分布列

  

  

原文地址:https://www.cnblogs.com/WTSRUVF/p/9721485.html

时间: 2024-10-12 15:45:21

聪聪和可可 HYSBZ - 1415(概率 + spfa + 记忆化dp)的相关文章

(spfa+记忆化) hdu 1428

漫步校园 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 3197    Accepted Submission(s): 960 Problem Description LL最近沉迷于AC不能自拔,每天寝室.机房两点一线.由于长时间坐在电脑边,缺乏运动.他决定充分利用每次从寝室到机房的时间,在校园里散散步.整个HDU校园呈方形布局,可划分

UVA 1541 - To Bet or Not To Bet 记忆化DP概率

Alexander Charles McMillan loves to gamble, and during his last trip to the casino he ran across a new game. It is played on a linear sequence of squares as shown below. A chip is initially placed on the Start square. The player then tries to move th

AC自动机+全概率+记忆化DP UVA 11468 Substring

题目传送门 题意:训练之南P217 分析:没有模板串也就是在自动机上走L步,不走到val[u] == v的节点的概率 PS:边读边insert WA了,有毒啊! #include <bits/stdc++.h> using namespace std; const int K = 20 + 5; const int L = 100 + 5; const int NODE = K * K; const int SIZE = 66; int idx[256], n; struct AC { int

HYSBZ 1415 - 聪聪和可可

http://vjudge.net/problem/viewProblem.action?id=20613 题意:不用说了,中文题. 这个题可以用概率DP来做. 题中要求猫抓到老鼠的时间期望.分析一下这个过程,如果猫在每单位时间里第一步移动没有抓到老鼠,它还可以继续移动一次.对于确定老鼠的位置,注意猫的每次移动都是固定的,而老鼠的移动位置却是不定的. 令dp[i][j]表示猫在i位置老鼠在j位置时,猫抓到老鼠的期望.next[i][j]表示猫从i位置到j位置时走最短路径需要移动到的第一个结点位置

bzoj 1415 [Noi2005]聪聪和可可——其实无环的图上概率

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1415 乍一看和"游走"一样.于是高斯消元.n^2状态,复杂度n^6-- 看看TJ,发现因为聪聪不是随便走的,所以聪聪一直逼近可可.故其实无环.可以记搜. (1A还是不错的) #include<iostream> #include<cstdio> #include<cstring> #include<queue> using name

【BZOJ】【1415】【NOI2005】聪聪和可可

数学期望+记忆化搜索 论文:<浅析竞赛中一类数学期望问题的解决方法>——汤可因  中的第一题…… Orz 黄学长 我实在是太弱,这么简单都yy不出来…… 宽搜预处理有点spfa的感觉= =凡是更新了的,都要重新入队更新一遍…… dp的记忆化搜索过程好厉害…… 期望这里一直很虚啊,赶紧再多做点题熟悉熟悉…… 1 /************************************************************** 2 Problem: 1415 3 User: Tunix

BZOJ 1415 NOI2005 聪聪和可可 期望DP+记忆化搜索 BZOJ200题达成&amp;&amp;NOI2005全AC达成

题目大意:给定一个无向图,聪聪在起点,可可在终点,每个时刻聪聪会沿最短路走向可可两步(如果有多条最短路走编号最小的点),然后可可会等概率向周围走或不动,求平均多少个时刻后聪聪和可可相遇 今天早上起床发现194了然后就各种刷--当我发现199的时候我决定把第200题交给05年NOI仅剩的一道题--结果尼玛调了能有一个小时--我居然没看到编号最小这个限制0.0 首先我们知道,由于聪聪走两步而可可走一步,所以聪聪一定能在有限的时刻追上可可,而且两人的距离随着时间进行单调递减 于是我们记忆化搜索 首先用

【BZOJ 1415】 1415: [Noi2005]聪聪和可可 (bfs+记忆化搜索+期望)

1415: [Noi2005]聪聪和可可 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1640  Solved: 962 Description Input 数据的第1行为两个整数N和E,以空格分隔,分别表示森林中的景点数和连接相邻景点的路的条数. 第2行包含两个整数C和M,以空格分隔,分别表示初始时聪聪和可可所在的景点的编号. 接下来E行,每行两个整数,第i+2行的两个整数Ai和Bi表示景点Ai和景点Bi之间有一条路. 所有的路都是无向的,即

【BZOJ1415】 [Noi2005]聪聪和可可 概率与期望

其实题不难,不知提交了几次...不能代码MD...注意一些基本问题...SB概率题 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #define N 1001 5 using namespace std; 6 double f[N][N]; 7 int n,m,cnt,a,b; 8 struct E{int next,to;}e[2*N+10]; 9 int head[N],ds[N],