标签: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