题目:
题解:
说是帮可可,最后还是看着聪聪把可可吃掉,灰姑娘你干啥吃的
状态还是比较容易想:f[i][j]表示聪聪在i,可可在j,聪聪吃掉可可时间期望,这样设计的基本支撑是:聪聪总是不断逼近可可,最后一定会吃掉可可。
我们可以bfs预处理出两点之间的最短距离,这样可以判断聪聪的行动了
那么几个基本的f[i][i]=0
dis[i][j]<=2,f[i][j]=1
设k为聪聪能达到的 距离j最近的 点,p=1/(du[j]+1)
f[i][j]=f[k][j]*p+Σf[k][vi]*p+1
代码:
#include <cstring>
#include <cstdio>
#include <queue>
#define INF 1e9
using namespace std;
const int N=1005;
int du[N],tot,nxt[N*2],point[N],v[N*2],dis[N][N],choose[N][N];double f[N][N];
void addline(int x,int y)
{
++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y;
++tot; nxt[tot]=point[y]; point[y]=tot; v[tot]=x;
}
void bfs(int s)
{
queue<int>q; q.push(s);
dis[s][s]=0;
while (!q.empty())
{
int now=q.front(); q.pop();
for (int i=point[now];i;i=nxt[i])
if (dis[s][v[i]]>INF)
dis[s][v[i]]=dis[s][now]+1,q.push(v[i]);
}
}
double dp(int x,int y)
{
if (f[x][y]!=-1.0) return f[x][y];
if (x==y) return f[x][y]=0.0;
if (dis[x][y]<=2) return f[x][y]=1.0;
f[x][y]=0;double p=1.0/(du[y]+1);int k=choose[choose[x][y]][y];
for (int i=point[y];i;i=nxt[i])
f[x][y]+=dp(k,v[i]);
f[x][y]+=dp(k,y);f[x][y]*=p;f[x][y]++;
return f[x][y];
}
int main()
{
freopen("sb.in","r",stdin);
int n,e,c,m;scanf("%d%d%d%d",&n,&e,&c,&m);
for (int i=1;i<=e;i++)
{
int x,y;scanf("%d%d",&x,&y);
addline(x,y);du[x]++; du[y]++;
}
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++) f[i][j]=-1.0;
memset(dis,0x7f,sizeof(dis));
for (int i=1;i<=n;i++)
bfs(i);
memset(choose,0x7f,sizeof(choose));//选择编号最小的,所以为max
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
{
if (dis[i][j]>INF) continue;
for (int k=point[i];k;k=nxt[k])
if (dis[i][j]==dis[v[k]][j]+1 && choose[i][j]>v[k])
choose[i][j]=v[k];
}
printf("%.3lf",dp(c,m));
}