bzoj 1415 期望dp + 记忆化搜索
思路:这个题看着感觉不能dp,其实是可以dp的,因为狼每次走两步,兔子每次走一步,每进行一轮以后,狼和兔子的距离
肯定是在接近的,没有相同的状态,dp之前预处理出来,每一步狼该往哪里走。
#include<bits/stdc++.h> #define LL long long #define fi first #define se second #define mk make_pair #define pii pair<int, int> using namespace std; const int N = 1000 + 7; const int M = 1e5 + 7; const int inf = 0x3f3f3f3f; const LL INF = 0x3f3f3f3f3f3f3f3f; const int mod = 1e9 +7; int n, m, S, T, dis[N][N], nx[N][N]; bool vis[N]; vector<int> edge[N]; double f[N][N]; void bfs(int s) { memset(vis, false, sizeof(vis)); dis[s][s] = 0; vis[s] = true; queue<int> que; for(int i = 0; i < edge[s].size(); i++) { int v = edge[s][i]; dis[s][v] = 1; nx[s][v] = v; vis[v] = true; que.push(v); } while(!que.empty()) { int u = que.front(); que.pop(); for(int i = 0; i < edge[u].size(); i++) { int v = edge[u][i]; if(!vis[v]) { dis[s][v] = dis[s][u] + 1; nx[s][v] = nx[s][u]; vis[v] = true; que.push(v); } else if(vis[v] && dis[s][u] + 1 == dis[s][v]) { nx[s][v] = min(nx[s][v], nx[s][u]); } } } } double dp(int i, int j) { if(f[i][j] >= 0) return f[i][j]; if(i == j) return f[i][j] = 0; if(nx[i][j] == j || nx[nx[i][j]][j] == j) return f[i][j] = 1; f[i][j] = 1; int nxi = nx[nx[i][j]][j]; double p = 1.0 / ((int) edge[j].size() + 1); for(int k = 0; k < edge[j].size(); k++) { f[i][j] += p * dp(nxi, edge[j][k]); } f[i][j] += p * dp(nxi, j); return f[i][j]; } int main() { scanf("%d%d", &n, &m); scanf("%d%d", &S, &T); for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) f[i][j] = -1; for(int i = 1; i <= m; i++) { int u, v; scanf("%d%d", &u, &v); edge[u].push_back(v); edge[v].push_back(u); } for(int i = 1; i <= n; i++) bfs(i); printf("%.3f\n", dp(S, T)); return 0; } /* */