BZOJ 1415: [Noi2005]聪聪和可可

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1415

题意:

有一个无向图,有N个景点1-N,有E条路。

可可在景点M处,之后每个时间单位,可可会选择去相邻的景点中的一个或停留在原景点不动。去这些地方的概率是相等的。

聪聪开始在景点C,聪聪会选择一个更靠近可可的景点,如果这样的景点有多个,则会选择一个标号最小的景点。

如果走完第一步以后仍然没吃到可可,她还可以在本段时间内再向可可走近一步。

在每个时间单位,聪聪先走,可可后走,若某时刻处于同一景点,则可可被吃到了。

求平均情况下,聪聪几步可以吃掉可可。

思路:

预处理出P[i][j]表示聪聪在i点可可在j点,聪聪下一步要到达的点。

dp[i][j]表示聪聪在i点可可在j点,聪聪抓住可可的平均步数。

dp[0][0] = 0,如果P[P[i][j]][j] = j 或 P[i][j] = j,那么dp[i][j] = 1。

除这两种情况,聪聪下一步的位置是P[P[i][j]][j],可可下一步是w[j][k]。概率为1/(j的度数+1)

那么可以得到递推式dp[i][j]=(segma(dp[p[p[i][j]][j][w[j][k]])+dp[p[p[i][j]][j]][j])/(t[i]+1) + 1

 1 /*
 2  * Problem:
 3  * Created Time:  2015/12/9 15:55:15
 4  * File Name: test.cpp
 5  */
 6 //#include <bits/stdc++.h>
 7 #include <iostream>
 8 #include <cstring>
 9 #include <cstdio>
10 #include <string>
11 #include <queue>
12 #include <vector>
13 using namespace std;
14 int N, E, C, M;
15 #define maxn 1010
16 vector <int> mp[maxn];
17 int p[maxn][maxn];
18 double dp[maxn][maxn];
19 int dist[maxn];
20 int t[maxn];
21 int min(int a, int b)
22 {
23     return a<b?a:b;
24 }
25 void bfs(int s)
26 {
27     queue <int> q;
28     q.push(s);
29     int vis[maxn];
30     memset(vis, 0, sizeof(vis));
31     memset(dist, -1, sizeof(dist));
32     dist[s] = 0;
33     vis[s] = 1;    
34     while(!q.empty())
35     {
36         int u = q.front(); q.pop();
37         for(int i = 0; i < mp[u].size(); i++)
38         {
39             if(dist[mp[u][i]] == -1)
40             {
41                 dist[mp[u][i]] = dist[u]+1;
42                 p[mp[u][i]][s] = u;
43                 q.push(mp[u][i]);
44             }
45             else if(dist[mp[u][i]] == dist[u]+1) p[mp[u][i]][s] = min(p[mp[u][i]][s], u);
46         }
47     }
48 }
49 double dfs(int from, int to)
50 {
51     if(dp[from][to] != -1) return dp[from][to];
52  
53     if(from == to) return dp[from][to] = 0;
54     if(p[from][to] == to || p[p[from][to]][to] == to) return dp[from][to] = 1.0;
55  
56     double sum = dfs(p[p[from][to]][to], to); //留在原地
57     for(int i = 0; i < mp[to].size(); i++)
58     {
59         sum += dfs(p[p[from][to]][to], mp[to][i]);
60     }
61     sum /= (t[to]+1.0); sum += 1;
62     return dp[from][to] = sum;
63  
64  
65 }
66 int main() 
67 {
68   //  freopen("in.txt", "r", stdin);
69     while(~scanf("%d%d", &N, &E))
70     {
71         scanf("%d%d", &C, &M);
72         for(int i = 1; i <= N; i++) mp[i].clear();
73         memset(t, 0, sizeof(t));
74         for(int i = 1; i <= E; i++)
75         {
76             int a, b;
77             scanf("%d%d", &a, &b);
78             t[a]++; t[b]++;
79             mp[a].push_back(b);
80             mp[b].push_back(a);  
81         }
82         memset(p, -1, sizeof(p));
83         for(int i = 1; i <= N; i++) bfs(i);
84         for(int i = 1; i <= N; i++)
85         {
86             for(int j = 1; j <= N; j++) dp[i][j] = -1;
87         }
88         double ans = dfs(C, M);
89         printf("%.3lf
", ans);
90           
91     }
92     return 0;
93 }
原文地址:https://www.cnblogs.com/titicia/p/5034102.html