题目
题解
开始做这道题(REfun T3)的时候,想只处理链的情况,发现 有一些记忆化搜索的意味。
变量声明:
du[i] 每个节点的度
p[i][j] 猫在i 老鼠在j时猫下一步可能走的情况;
dis[i][j]:i和j两点的距离
f[i][j] 猫在i 老鼠在j时的期望值;
首先处理处上面的变量,然后记忆化搜索,
f[i][j]=(f[i][j]+dfs(p[p[i][j]][j],j))/(double)(du[j]+1)+1;
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
const int inf=2*1e9;
using namespace std;
int n,m,s,t,x,y,du[1001],p[1001][1001],dis[1001][1001];//du每个节点的度
double f[1001][1001];
struct Edge{
int to,next;
}edge[2001];
int head[1001],num_edge;
double ans;
void add_edge(int from,int to)
{
edge[++num_edge].next=head[from];
edge[num_edge].to=to;
head[from]=num_edge;
}
int q[2001];
void bfs(int s)
{
int front=0,tail=1;
q[1]=s; dis[s][s]=0;
while (front!=tail)
{
int now=q[++front];
for (int i=head[now]; i!=0; i=edge[i].next)
{
int to=edge[i].to;
if (dis[s][to] == -1)
{
dis[s][to]=dis[s][now]+1;
q[++tail]=to;
}
}
}
}
double dfs(int i,int j)//记忆化搜索,表示从i到j期望的时间是多少
{
if (f[i][j]!=-1.0) return f[i][j];
if (i==j) return f[i][j]=0.0;//已经到达
if (p[i][j] == j) return f[i][j]=1.0;//还有一步 不要忘记赋值
if (p[p[i][j]][j] == j) return f[i][j]=1.0;//还有两步
f[i][j]=0.0;
for (int k=head[j]; k!=0; k=edge[k].next)
f[i][j]+=dfs(p[p[i][j]][j],edge[k].to);
f[i][j]=(f[i][j]+dfs(p[p[i][j]][j],j))/(double)(du[j]+1)+1;//du[j]
return f[i][j];
}
int main()
{
scanf("%d%d%d%d",&n,&m,&s,&t);
for (int i=1; i<=m; i++)
{
scanf("%d%d",&x,&y);
add_edge(x,y); add_edge(y,x);
du[x]++; du[y]++;
}
for (int i=0; i<=n; i++)
for (int j=0; j<=n; j++)
f[i][j]=-1;//答案数组初始化
memset(dis,-1,sizeof(dis));
for (int i=1; i<=n; i++)
bfs(i);
memset(p,0x7f,sizeof(p));//选择编号较小的点
for (int i=1; i<=n; i++)
for (int k=head[i]; k!=0; k=edge[k].next)
{
int to=edge[k].to;
for (int j=1; j<=n; j++)
if (dis[to][j]+1==dis[i][j] && p[i][j]>to)
p[i][j]=to;
}
printf("%.3lf\n",dfs(s,t));
return 0;
}
总结
注意记忆化搜索的应用
好好学概率期望dp啊啊啊