• bzoj 1415: [Noi2005]聪聪和可可 期望dp+记忆化搜索


    期望dp水题~ 

    你发现每一次肯定是贪心走 2 步,(只走一步的话就可能出现环) 

    然后令 $f[i][j]$ 表示聪在 $i$,可在 $j$,且聪先手两个人碰上面的期望最小次数. 

    用记忆化搜索转移就行了. 

    code: 

    #include <queue> 
    #include <cstdio> 
    #include <vector> 
    #include <cstring> 
    #include <algorithm>  
    #define N 1004   
    #define LL long long      
    #define pb push_back   
    #define setIO(s) freopen(s".in","r",stdin) 
    using namespace std;         
    int n,m; 
    queue<int>q;   
    vector<int>G[N];   
    double dp[N][N];    
    int nxt[N][N],dis[N][N],vis[N],d[N],vised[N][N];        
    double f(int a,int b) 
    { 
        if(a==b)   return 0.0;       
        if(nxt[a][b]==b)  return 1.00;               
        if(nxt[nxt[a][b]][b]==b)   return 1.00;    
        if(vised[a][b])   return dp[a][b];           
        vised[a][b]=1;   
        dp[a][b]=0.000;              
        for(int i=0;i<G[b].size();++i)   
        {
            int v=G[b][i];            
            dp[a][b]+=(f(nxt[nxt[a][b]][b], v)+1.00)/(double)G[b].size();           
        }           
        return dp[a][b];                        
    }
    int main() 
    {    
        int i,j,A,B; 
        scanf("%d%d%d%d",&n,&m,&A,&B);   
        for(i=1;i<=m;++i) 
        {
            int a,b; 
            scanf("%d%d",&a,&b);   
            G[a].pb(b),G[b].pb(a); 
        }   
        for(i=1;i<=n;++i)  
        {
            memset(vis,0,sizeof(vis)); 
            d[i]=0; 
            q.push(i);  
            vis[i]=1;       
            while(!q.empty()) 
            {
                int u=q.front();  q.pop();    
                for(j=0;j<G[u].size();++j)
                {
                    int v=G[u][j]; 
                    if(!vis[v]) 
                    {
                        vis[v]=1; 
                        d[v]=d[u]+1; 
                        q.push(v);      
                    }
                }  
            }        
            nxt[i][i]=i;    
            for(j=1;j<=n;++j)    
            {
                if(j==i)    continue;
                int mx=0,k,v; 
                for(k=0;k<G[j].size();++k) 
                {
                    v=G[j][k];   
                    if(d[j]==d[v]+1&&(v<mx||!mx))     mx=v;      
                }   
                nxt[j][i]=mx;       
            }
        }          
        for(i=1;i<=n;++i)  G[i].pb(i);    
        printf("%.3f
    ",f(A,B));    
        return 0;  
    }   
    

      

  • 相关阅读:
    求菲波那契数列的第n个数
    一个球,初始高度100,每次落下回弹一半高度,求第n次落下球走的距离
    MySQL优化
    linux常用命令2
    win7安装ANT
    win7配置java环境变量
    kvm虚拟机磁盘文件读取小结
    kvm linux虚拟机在线扩展磁盘
    binlog2sql
    linux上 查看mysql的binglog日志
  • 原文地址:https://www.cnblogs.com/guangheli/p/11773686.html
Copyright © 2020-2023  润新知