码迷,mamicode.com
首页 > 其他好文 > 详细

[填坑]期望概率DP 试炼场

时间:2017-10-18 10:07:11      阅读:152      评论:0      收藏:0      [点我收藏+]

标签:fine   分享   com   scanf   logs   记忆化   name   main   while   

完成了新手村任务的Hallmeow,来到了试炼场提升自己

正当我在网上找题练习的时候,突然意识到原来的题库里有这个专项,但我一共没做几道题而且还浑浑噩噩的,OD找的题质量都没话说,于是就把这些弄懂吧

 

[试炼场]BZOJ 1415 聪聪与可可

聪聪可以一下走两步,而且聪聪先走,可可后走

我们预处理出来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;
}

  

[填坑]期望概率DP 试炼场

标签:fine   分享   com   scanf   logs   记忆化   name   main   while   

原文地址:http://www.cnblogs.com/Hallmeow/p/7684886.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!