bzoj1415 聪聪与可可 概率dp

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

题目大意是:给一张无权无向图,一个人去追另一个人,保证被追的人初始点编号小于追的人初始点编号,被追的人随机选择走一条边或选择不走,追的人走能接近被追的人且终点编号最小的一条边,单回合可走两步,求期望步数。

首先,读入图后,我们需要预处理出每一回合,严格地讲是每一步追的人选择的边。如果说这个点可以在一步范围内追到就取追到的这个点,如果两点重合(这个在接下来会有用)就设为该点,否则,接近它的这个点就必须与扩展到它的这个点步数相同。显然这个要选择bfs。

bfs完成后,我们设数组f[i][j]为追的人在i,被追的人在j,期望追到的步数。对整张图记忆化搜索,如果已经到一块返回零,一步(之前的定义,第二步留在原地)或两步追到返回1,追不到则对被追的人每种选择进行递归搜索。

实际操作时还要注意:追的人选择能接近被追的人且终点编号最小的边,所以要用vector存图并对终点字典序排序。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<vector>
 6 using namespace std;
 7 const int maxn=985,maxm=985;
 8 vector<int>G[maxn];
 9 int du[maxn];
10 double f[maxn][maxn];
11 int n,e,c,m;
12 #include<queue>
13 int near[maxn][maxn];
14 void Spfa(int x)
15 {
16     bool vis[maxn]={0};
17     queue<int>q;
18     near[x][x]=x;
19     q.push(x);vis[x]=1;
20     while(!q.empty())
21     {
22         int t=q.front();q.pop();
23         for(int i=0;i<G[t].size();i++)
24         {
25             int v=G[t][i];
26             if(vis[v])continue;
27             if(t==x)near[x][v]=v;
28             else near[x][v]=near[x][t];
29             vis[v]=1;
30             q.push(v);
31         }
32     }
33 }
34 const double eps=1e-6;
35 double dp(int from,int to)
36 {
37     if(f[from][to]>eps)return f[from][to];
38     if(from==to)return 0;
39     int go=near[near[from][to]][to];
40     if(go==to)return f[from][to]=1;
41     double ans=dp(go,to);
42     for(int i=0;i<G[to].size();i++)
43     {
44         int v=G[to][i];
45         ans+=dp(go,v);
46     }
47     ans/=(double)(du[to]+1);
48     ans++;
49     return f[from][to]=ans;
50 }
51 int haha()
52 {
53     //freopen("cchkk.in","r",stdin);
54     //freopen("cchkk.out","w",stdout);
55     scanf("%d%d",&n,&e);scanf("%d%d",&c,&m);
56     for(int i=1;i<=e;i++)
57     {
58         int x,y;scanf("%d%d",&x,&y);
59         G[x].push_back(y);G[y].push_back(x);
60         du[x]++;du[y]++;
61     }
62     for(int i=1;i<=n;i++)sort(G[i].begin(),G[i].end());
63     for(int i=1;i<=n;i++)Spfa(i);
64     printf("%0.3lf",dp(c,m));
65 }
66 int sb=haha();
67 int main(){;}
只要是活着的东西,就算是神我也杀给你看。
原文地址:https://www.cnblogs.com/Loser-of-Life/p/7181875.html