[NOI2005] 聪聪与可可

[NOI2005] 聪聪与可可

题目大意:给定一个无向图,聪聪在起点,可可在终点,每个时刻聪聪会沿最短路走向可可两步(如果有多条最短路走编号最小的点),然后可可会等概率向周围走或不动,求平均多少个时刻后聪聪和可可相遇, \(1\leq N,E\leq 1000\)

Solution

  1. \(n\)\(bfs\)求出点对间的最短距离
  2. 预处理出每个点前往每个点的下一步
  3. 记忆化搜索
  • 状态:\(f[i][j]\)表示聪聪在\(i\)点,可可在\(j\)点,过多少时间相遇的期望

不要忘了聪聪可以走两步哟

Code

#include <bits/stdc++.h>

using namespace std;

const int N = 1005;

int n, k, c, m, ecnt;
int head[N], dis[N][N], qwq[N][N], deg[N];
double f[N][N];

struct Edge{
    int to, next;
}e[N << 1];

inline void adde(int x, int y) {
    e[++ecnt].to = y;
    e[ecnt].next = head[x];
    head[x] = ecnt;
}

double dp(int x, int y) {
    
    if(f[x][y] != -1.0) 
        return f[x][y];
    if(x == y)
        return f[x][y] = 0;
    if(qwq[x][y] == y) 
        return f[x][y] = 1.0;
    if(qwq[qwq[x][y]][y] == y)
        return f[x][y] = 1.0;//聪聪可以走两步QAQ
    f[x][y] = 0.0;
    for(int i = head[y]; i; i = e[i].next) {
        f[x][y] += dp(qwq[qwq[x][y]][y], e[i].to);
    } 
    f[x][y] = (f[x][y] + dp(qwq[qwq[x][y]][y], y)) / double(deg[y] + 1) + 1;//四舍五入 
    return f[x][y];
}

int main() {
    scanf("%d %d %d %d", &n, &k, &c, &m);
    for(int i = 1, la, lb; i <= k; ++i) {
        scanf("%d %d", &la, &lb);
        adde(la, lb);
        adde(lb, la);
        deg[la]++;
        deg[lb]++;
    }
    for(int i = 0; i <= n; ++i)
        for(int j = 0; j <= n; ++j) {
            f[i][j] = -1.0;
        }
    memset(dis, -1, sizeof(dis));
    for(int i = 1; i <= n; ++i) {
        dis[i][i] = 0;
        queue <int> q;
        q.push(i);//是push(i),不是push(1)
        while(!q.empty()) {
            int x = q.front();
            q.pop();
            for(int j = head[x]; j; j = e[j].next) {
                if(dis[i][e[j].to] == -1) {
                    dis[i][e[j].to] = dis[i][x] + 1;
                    q.push(e[j].to);
                }
            }
        }
    }
    memset(qwq, 0x3f, sizeof(qwq));
    for(int i = 1; i <= n; ++i)
        for(int j = head[i]; j; j = e[j].next) {
            for(int l = 1; l <= n; ++l) {
                if(dis[i][l] == dis[e[j].to][l] + 1 && qwq[i][l] > e[j].to)
                    qwq[i][l] = e[j].to;
            }
        }
    printf("%.3lf", dp(c, m));
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/LMSH7/p/9708803.html