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\n", ans); 90 91 } 92 return 0; 93 }