P4206 [NOI2005] 聪聪与可可 题解
Sol
你会发现在一个时刻,聪聪走到哪里是固定的,所以我们从这里入手。
我们考虑预处理 \(nxt_{i,j}\) 表示聪聪在 \(i\),可可在 \(j\) 时,聪聪下一步的位置。
如果我们把 \(i \to j\) 的路径扣出来,时间复杂度是 \(O(n^3)\) 的,需要优化。
我们可以跑 \(n\) 次 BFS,把任意两点 \(x,y\) 的距离 \(dis_{x,y}\) 用 \(O(n^2)\) 的时间求出。
这样的话,求出所以 \(nxt_{i,j}\) 的总时间复杂度就是 \(O(\eta n^2)\) 的了,\(\eta\) 是枚举 \(i\) 走 \(2\) 步到达的点所花的时间,随机数据下接近于 \(2\)。
接下来我们考虑求答案,我们设 \(dp_{i,j}\) 表示聪聪在 \(i\),可可在 \(j\) 的回合数的期望,转移分 \(3\) 种情况:
- 这回合什么也不用干就结束,即 \(i=j\) 时,期望为 \(0\)。
- 这回合可可不需要移动就结束,即 \(dis_{i,j} \le 2\) 是,期望为 \(1\)。
- 这回合可可需要移动,那么聪聪肯定会固定移动到 \(nxt_{i,j}\),接下来要讨论的是可可的移动,可可会等概率地移动到他可移动到的位置,即 \(dp_{i,j}=1 + \sum\limits_{j \to j'}dp_{nxt_{i,j},j'}(\frac{1}{du_j+1})\)。
由于转移顺序相对复杂,所以我们考虑记忆化搜索,时间复杂度 \(O(n^2)\)。
总时间复杂度 \(O(\eta n^2)\)。
Code
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1005;
int n,m,st,ed,nxt[N][N],dis[N][N],ls[N][N],du[N];
double dp[N][N];
vector<int>nbr[N];
void bfs(int s)
{
queue<int>q;
q.push(s);
dis[s][s]=0;
while(q.empty()==false)
{
int cur=q.front();
q.pop();
for(int nxt:nbr[cur])
if(dis[s][nxt]>1e13)
{
dis[s][nxt]=dis[s][cur]+1;
q.push(nxt);
}
}
return ;
}
double M_dfs(int cc,int kk)
{
if(cc==kk)
return 0;
if(dis[cc][kk]<=2)
return 1;
if(dp[cc][kk]!=0)
return dp[cc][kk];
double gl=1.0/du[kk];
int than=nxt[cc][kk];
dp[cc][kk]=M_dfs(than,kk)*gl+1;
for(int p:nbr[kk])
dp[cc][kk]+=M_dfs(than,p)*gl;
return dp[cc][kk];
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cin>>n>>m>>st>>ed;
for(int i=1;i<=m;i++)
{
int x,y;
cin>>x>>y;
nbr[x].push_back(y);
nbr[y].push_back(x);
du[x]++,du[y]++;
}
memset(dis,0x3f,sizeof dis);
for(int i=1;i<=n;i++)
{
bfs(i);
du[i]++;
}
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
if(dis[i][j]<=2)
{
nxt[i][j]=j;
continue;
}
for(int k:nbr[i])
for(int p:nbr[k])
{
if(p==i)
continue;
if(dis[nxt[i][j]][j]>dis[p][j])
nxt[i][j]=p,ls[i][j]=k;
else if(dis[nxt[i][j]][j]==dis[p][j]&&k<ls[i][j])
nxt[i][j]=p,ls[i][j]=k;
else if(dis[nxt[i][j]][j]==dis[p][j]&&k==ls[i][j]&&p<nxt[i][j])
nxt[i][j]=p,ls[i][j]=k;
}
}
// for(int i=1;i<=n;i++)
// {
// for(int j=1;j<=n;j++)
// cerr<<nxt[i][j]<<" ";
// cerr<<"\n";
// }
cout<<fixed<<setprecision(3)<<M_dfs(st,ed);
return 0;
}

浙公网安备 33010602011771号