您的位置:首页 > 其它

BZOJ 1415: [Noi2005]聪聪和可可

2015-12-09 20:24 225 查看
题目链接: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

/*
* Problem:
* Created Time:  2015/12/9 15:55:15
* File Name: test.cpp
*/
//#include <bits/stdc++.h>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <string>
#include <queue>
#include <vector>
using namespace std;
int N, E, C, M;
#define maxn 1010
vector <int> mp[maxn];
int p[maxn][maxn];
double dp[maxn][maxn];
int dist[maxn];
int t[maxn];
int min(int a, int b)
{
return a<b?a:b;
}
void bfs(int s)
{
queue <int> q;
q.push(s);
int vis[maxn];
memset(vis, 0, sizeof(vis));
memset(dist, -1, sizeof(dist));
dist[s] = 0;
vis[s] = 1;
while(!q.empty())
{
int u = q.front(); q.pop();
for(int i = 0; i < mp[u].size(); i++)
{
if(dist[mp[u][i]] == -1)
{
dist[mp[u][i]] = dist[u]+1;
p[mp[u][i]][s] = u;
q.push(mp[u][i]);
}
else if(dist[mp[u][i]] == dist[u]+1) p[mp[u][i]][s] = min(p[mp[u][i]][s], u);
}
}
}
double dfs(int from, int to)
{
if(dp[from][to] != -1) return dp[from][to];

if(from == to) return dp[from][to] = 0;
if(p[from][to] == to || p[p[from][to]][to] == to) return dp[from][to] = 1.0;

double sum = dfs(p[p[from][to]][to], to); //留在原地
for(int i = 0; i < mp[to].size(); i++)
{
sum += dfs(p[p[from][to]][to], mp[to][i]);
}
sum /= (t[to]+1.0); sum += 1;
return dp[from][to] = sum;

}
int main()
{
//  freopen("in.txt", "r", stdin);
while(~scanf("%d%d", &N, &E))
{
scanf("%d%d", &C, &M);
for(int i = 1; i <= N; i++) mp[i].clear();
memset(t, 0, sizeof(t));
for(int i = 1; i <= E; i++)
{
int a, b;
scanf("%d%d", &a, &b);
t[a]++; t[b]++;
mp[a].push_back(b);
mp[b].push_back(a);
}
memset(p, -1, sizeof(p));
for(int i = 1; i <= N; i++) bfs(i);
for(int i = 1; i <= N; i++)
{
for(int j = 1; j <= N; j++) dp[i][j] = -1;
}
double ans = dfs(C, M);
printf("%.3lf\n", ans);

}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: