BZOJ 1415: [Noi2005]聪聪和可可 概率DP,记忆化搜索,BFS

来源:互联网 发布:网络理财哪里做得好 编辑:程序博客网 时间:2024/05/22 01:42

这里写图片描述

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

PoPo大爷写了非常详解的题解,http://blog.csdn.net/PoPoQQQ/article/details/40896403 对蒟蒻来说这个题的信

息量还是很大的,但实际上又很水,这就是信息学的魅力吧。

首先我们知道,由于聪聪走两步而可可走一步,所以聪聪一定能在有限的时刻追上可可,而且两人的距离随着时间进行

单调递减

于是我们记忆化搜索

首先用预处理出一个数组p[i][j],表示当聪聪在点i,可可在点j时聪聪下一步走哪个点 这个从每个点出发跑一遍SPFA就

可以处理出来

然后就可以记忆化搜索了 令f[i][j]为当聪聪在点i,可可在点j时的期望相遇时

若i==j 则f[i][j]=0

若p[i][j]==j||p[p[i][j]][j]==j则f[i][j]=1

否则令temp=p[p[i][j]][j],则有

这里写图片描述

我为了不统计度数,直接加了一条自己到自己的边,然后直接BFS,懒得spfa了。

//BZOJ 1415#include <bits/stdc++.h>using namespace std;const int maxn = 1010;const int inf=0x3f3f3f3f;struct edge{    int v, nxt;    edge(){}    edge(int v,int nxt):v(v), nxt(nxt){}}E[maxn*5];int head[maxn], edgecnt;void init(){    edgecnt = 0;    memset(head, -1, sizeof(head));}void add(int u, int v){    E[edgecnt].v=v,E[edgecnt].nxt=head[u],head[u]=edgecnt++;}int dist[maxn][maxn], p[maxn][maxn];///p[i][j]聪聪在i点可可在j点,聪聪下一步走哪个点int n, m, s, t;double f[maxn][maxn];bool vis[maxn][maxn];double dfs(int x, int y){    if(vis[x][y]) return f[x][y];    vis[x][y]=1;    if(dist[x][y]==0) return f[x][y]=0.0;    if(dist[x][y]<=2) return f[x][y]=1.0;    double val = 0;    int cnt=0;    for(int i=head[y];~i;i=E[i].nxt){        cnt++;        val+=dfs(p[p[x][y]][y],E[i].v);    }    return f[x][y]=val/cnt+1.0;}queue <int> que;void bfs(int s){    que.push(s);    dist[s][s]=0;    while(!que.empty()){        int u=que.front(); que.pop();        for(int i=head[u];~i;i=E[i].nxt){            int v=E[i].v;            if(dist[s][v]==-1){                dist[s][v]=dist[s][u]+1;                que.push(v);            }        }    }}int main(){    scanf("%d%d%d%d", &n,&m,&s,&t);    init();    while(m--){        int a,b;        scanf("%d%d", &a, &b);        add(a, b);        add(b, a);    }    memset(dist, -1, sizeof(dist));    for(int k=1; k<=n; k++){        bfs(k);        for(int j=1; j<=n; j++){            if(j!=k){                int mx = inf;                for(int i=head[j];~i;i=E[i].nxt){                    if(mx>dist[k][E[i].v]){                        mx = dist[k][E[i].v];                        p[j][k]=E[i].v;                    }                    else if(mx==dist[k][E[i].v]){                        p[j][k]=min(p[j][k],E[i].v);                    }                }            }        }    }    for(int i=1; i<=n; i++) add(i,i);    printf("%.3lf\n", dfs(s, t));    return 0;}
0 0
原创粉丝点击