zoukankan      html  css  js  c++  java
  • [NOI2005]聪聪与可可

    题目链接:Click here

    Solution:

    首先设(f(i,j))表示聪聪在点(i),可可在点(j)时的期望时间,设(tot_x)表示与(x)相邻的点的个数,(to_i)表示与(i)相邻的点集

    因为可可每次可能走到与自己相邻的某个点,也可能不动,这些选择都是等概率的,则我们可以得出式子:

    [f(i,j)=frac{1}{tot_j+1}(1+f(now,j)+sum_{vin to_j}1+f(now,v))\ f(i,j)=frac{1}{tot_j+1}(f(now,j)+sum_{vin to_j}f(now,v))+1 ]

    dp的过程我们可以用记忆化搜索来完成,现在我们只需要知道对于每一个(f(i,j))(now)是多少就行了

    这个也很简单,先用spfa处理出距离,再来预处理就好了,最后我们只需要输出(f(S,T))就行了

    Code:

    #include<bits/stdc++.h>
    const int N=1e3+1;
    const int inf=2147483647;
    using namespace std;
    int n,m,s,t,cnt,head[N],dis[N][N];
    int go[N][N],apr[N][N],vis[N];
    double f[N][N];
    struct Edge{int nxt,to;}edge[N<<1];
    void ins(int x,int y){
    	edge[++cnt].nxt=head[x];
    	edge[cnt].to=y;head[x]=cnt;
    }
    queue<int> q;
    void spfa(int v0){
    	for(int i=1;i<=n;i++)
    		dis[v0][i]=inf;
    	dis[v0][v0]=0;q.push(v0);
    	memset(vis,0,sizeof(vis));
    	while(!q.empty()){
    		int x=q.front();q.pop();vis[x]=0;
    		for(int i=head[x];i;i=edge[i].nxt){
    			int y=edge[i].to;
    			if(dis[v0][x]+1<dis[v0][y]){
    				dis[v0][y]=dis[v0][x]+1;
    				if(!vis[y]) q.push(y),vis[y]=1;
    			}
    		}
    	}
    }
    double dfs(int x,int y){
    	if(apr[x][y]) return f[x][y];
    	apr[x][y]=1;int tot=1;
    	int u1=go[x][y],u2=go[u1][y];
    	if(u1==y||u2==y) return f[x][y]=1.0;
    	f[x][y]=1.0;
    	for(int i=head[y];i;i=edge[i].nxt) ++tot;
    	for(int i=head[y];i;i=edge[i].nxt){
    		int to=edge[i].to;
    		f[x][y]+=1.0*1/tot*dfs(u2,to);
    	}f[x][y]+=1.0/tot*dfs(u2,y);
    	return f[x][y];
    }
    int read(){
    	int x=0,f=1;char ch=getchar();
    	while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    	while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}
    	return x*f;
    }
    int main(){
    	n=read(),m=read(),s=read(),t=read();
    	for(int i=1;i<=m;i++){
    		int x=read(),y=read();
    		ins(x,y),ins(y,x);
    	}
    	for(int i=1;i<=n;i++) spfa(i);
    	for(int i=1;i<=n;i++) apr[i][i]=1,f[i][i]=0.0;
    	memset(go,0x3f,sizeof(go));
    	for(int i=1;i<=n;i++)	
    		for(int u=head[i];u;u=edge[u].nxt){
    			int y=edge[u].to;
    			for(int j=1;j<=n;j++)
    				if(dis[y][j]+1==dis[i][j])
    					go[i][j]=min(go[i][j],y);
    		}printf("%.3lf
    ",dfs(s,t));
    	return 0;
    }
    
  • 相关阅读:
    MongoDB 数组
    MongoDB 内嵌文档
    MongoDB 聚合操作
    MongoDB 文档的删除操作
    MongoDB 文档的更新操作
    MongoDB 文档的查询和插入操作
    MongoDB 安装和可视化工具
    SSIS 容器
    SSISDB2:SSIS工程的操作实例
    Replication:distribution 中一直在运行 waitfor delay @strdelaytime 语句
  • 原文地址:https://www.cnblogs.com/NLDQY/p/11170426.html
Copyright © 2011-2022 走看看