标签:fine 分享 com scanf logs 记忆化 name main while
完成了新手村任务的Hallmeow,来到了试炼场提升自己
正当我在网上找题练习的时候,突然意识到原来的题库里有这个专项,但我一共没做几道题而且还浑浑噩噩的,OD找的题质量都没话说,于是就把这些弄懂吧
聪聪可以一下走两步,而且聪聪先走,可可后走
我们预处理出来p[ i ][ j ]为聪聪在 i ,可可在 j 时聪聪下一步要走到哪,用n遍spfa即可
显然,dp[ i ][ i ]=0
显然,如果p[ i ][ j ]= j 或者 p[ p[ i ][ j ] ][ j ]= j 那么没等到可可走就被吃掉了,dp[ i ][ j ]=1
设 w 为与 j 有连边的点, t 为 j 的度

需要记忆化搜索,用已经更新的更新未更新的
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
#define pos(i,a,b) for(int i=(a);i<=(b);i++)
#define pos2(i,a,b) for(int i=(a);i>=(b);i--)
#define N 2000
struct haha{
int next,to;
}edge[N];
int head[N],cnt=1;
int degree[N];
void add(int u,int v){
degree[u]++;
edge[cnt].to=v;
edge[cnt].next=head[u];
head[u]=cnt++;
}
int n,m;
int a,b;
int dis[N],flag[N];
int p[N][N];
void spfa(int st)
{
int f[N],q[65540],v[N],from[N];
unsigned short r,h;
int i;
memset(f,0x3f,sizeof f);
f[st]=0;q[++r]=st;
while(r!=h)
{
int x=q[++h];
v[x]=0;
for(i=head[x];i;i=edge[i].next)
if(f[edge[i].to]>f[x]+1||f[edge[i].to]==f[x]+1&&x<from[edge[i].to])
{
f[edge[i].to]=f[x]+1;
from[edge[i].to]=x;
if(!v[edge[i].to])
v[edge[i].to]=1,q[++r]=edge[i].to;
}
}
for(i=1;i<=n;i++)
if(i!=st)
p[i][st]=from[i];
}
double ans[N][N];
double dfs(int x,int y){
if(x==y) return ans[x][y]=0;
if(p[x][y]==y) return ans[x][y]=1;
if(p[p[x][y]][y]==y) return ans[x][y]=1;
if(ans[x][y]>=-1e-7)
return ans[x][y];
double re=1.0;int temp=p[p[x][y]][y];
for(int i=head[y];i;i=edge[i].next){
re+=dfs(temp,edge[i].to)/(degree[y]+1);
}
re+=dfs(temp,y)/(degree[y]+1);
return ans[x][y]=re;
}
int main(){
scanf("%d%d%d%d",&n,&m,&a,&b);
pos(i,1,m){
int x,y;
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
pos(i,1,n){
spfa(i);
}
memset(ans,200,sizeof(ans));
printf("%0.3lf",dfs(a,b));
return 0;
}
标签:fine 分享 com scanf logs 记忆化 name main while
原文地址:http://www.cnblogs.com/Hallmeow/p/7684886.html