• COCI20122013 Contest#5 F


    COCI20122013 Contest#5 F

    不知道题解在写什么.jpg

    Part1 : Naive的dp

    (dp_{i,a,b,j})表示当前时刻(i),两队比分为(a,b),球在(j)手上的概率

    转移非常简单就不说了,单次转移为(O(n)),复杂度为(O(n^2r^2T))

    在优秀卡常+O2下跑进700ms

    优化的话:
    1.float

    2.分小块加速

    3.循环展开

    #include<bits/stdc++.h>
    using namespace std;
    #pragma GCC optimize(2)
    typedef float db;
    #define reg register
    #define rep(i,a,b) for(reg int i=a,i##end=b;i<=i##end;++i)
    #define drep(i,a,b) for(reg int i=a,i##end=b;i>=i##end;--i)
    template <class T> inline void cmin(T &a,const T &b){ ((a>b)&&(a=b)); }
    template <class T> inline void cmax(T &a,const T &b){ ((a<b)&&(a=b)); }
    
    char IO;
    template <class T=int> T rd(){
    	T s=0; int f=0;
    	while(!isdigit(IO=getchar())) if(IO=='-') f=1;
    	do s=(s<<1)+(s<<3)+(IO^'0');
    	while(isdigit(IO=getchar()));
    	return f?-s:s;
    }
    
    const int INF=1e9+10;
    const db eps=1e-12;
    
    int n,R,T;
    db dp[510][11][11][210],p[410],sz[410],ans[11][11];
    struct Edge{
    	int to,nxt;
    } e[80000];
    int head[410],ecnt;
    void AddEdge(int u,int v) {
    	e[++ecnt]=(Edge){v,head[u]};
    	head[u]=ecnt;
    }
    int E[410][410],G[410][410]; 
    const int D=5;
    db tmp[210][1<<D];
    
    int main(){
    	n=rd(),R=rd(),T=rd();
    	int m=(n*2+D-1)/D;
    	rep(i,1,n*2) {
    		scanf("%f",&p[i]);
    		int e=rd(),f=rd();
    		sz[i]=e+f+1;
    		rep(j,1,e) {
    			int x=rd();
    			if(i>n) x+=n;
    			E[i][x]=1;
    		}
    		rep(j,1,f) {
    			int x=rd();
    			if(i<=n) x+=n;
    			E[i][x]=1;
    		}
    		rep(j,1,m) {
    			int f=(j-1)*D+1;
    			rep(k,0,D-1) G[i][j]|=E[i][f+k]<<k;
    			if(G[i][j]) AddEdge(i,j);
    		}
    	}
    	dp[0][0][0][1]=1;
    	for(reg int i=0;i<=T;++i) {
    		for(reg int a=0;a<=R;++a) {
    			for(reg int b=0;b<=R;++b) {
    				for(reg int j=1;j<=n*2;++j) if(dp[i][a][b][j]>eps) {
    					if(a==R || b==R || i==T) { ans[a][b]+=dp[i][a][b][j]; continue; }
    					db t=dp[i][a][b][j]/sz[j];
    					for(reg int k=1;k<=m;k+=4) {
    						tmp[k][G[j][k]]+=t;
    						tmp[k+1][G[j][k+1]]+=t;
    						tmp[k+2][G[j][k+2]]+=t;
    						tmp[k+3][G[j][k+3]]+=t;
    					}
    					if(j<=n) {
    						dp[i+1][a][b][n+1]+=t*(1-p[j]);
    						dp[i+1][a+1][b][n+1]+=t*p[j];
    					} else {
    						dp[i+1][a][b][1]+=t*(1-p[j]);
    						dp[i+1][a][b+1][1]+=t*p[j];
    					}
    				}
    				for(reg int j=1;j<=m;++j) {
    					int f=(j-1)*D+1;
    					rep(k,1,(1<<D)-1) {
    						(k&1) &&  (dp[i+1][a][b][f]+=tmp[j][k]);
    						(k&2) &&  (dp[i+1][a][b][f+1]+=tmp[j][k]);
    						(k&4) &&  (dp[i+1][a][b][f+2]+=tmp[j][k]);
    						(k&8) &&  (dp[i+1][a][b][f+3]+=tmp[j][k]);
    						(k&16) &&  (dp[i+1][a][b][f+4]+=tmp[j][k]);
    						tmp[j][k]=0;
    					}
    				}
    			}
    		}
    	}
    	rep(i,0,R) rep(j,0,R) if(i!=R || j!=R) printf("%.10f
    ",ans[i][j]);
    }
    
    

    [ ]

    Part2: 状态割裂

    定义每个球进的时间为关键点,我们发现关键点的状态非常单一,只有两种

    一个合法的转移序列可以被分为若干关键点的段以及最后一段到达(T)之后停止转移

    考虑预处理两个关键点之间的转移概率

    (g_{a,b,i})为当球在(a)队一号队员时,(i)次后(b)队进球的概率

    可以枚举(a),类似上面的(dp),去掉比分的一维即可

    预处理复杂度为(O(Tn^2))

    然后(dp)时直接枚举两个关键点转移,令

    (h_{i,a,b,j})时刻(i)比分为(a,b),球在(j)队一号队员手上的概率

    转移分两种

    1.枚举下一个在(T)以内的关键点转移

    复杂度为(O(T))

    2.考虑在(T)以内的时间不再出现进球了

    需要预处理出当球在(i)队手上时,(j)次内出现进球的概率(s_{i,j}),这个直接由(g)数组累前缀和即可

    (dp)关键点的复杂度为(O(T^2r^2))

    大概比上面代码快4-5倍

    #include<bits/stdc++.h>
    using namespace std;
    #pragma GCC optimize(2)
    typedef float db;
    #define reg register
    #define rep(i,a,b) for(reg int i=a,i##end=b;i<=i##end;++i)
    #define drep(i,a,b) for(reg int i=a,i##end=b;i>=i##end;--i)
    
    char IO;
    template <class T=int> T rd(){
        T s=0; int f=0;
        while(!isdigit(IO=getchar())) if(IO=='-') f=1;
        do s=(s<<1)+(s<<3)+(IO^'0');
        while(isdigit(IO=getchar()));
        return f?-s:s;
    }
    
    const int INF=1e9+10;
    const db eps=1e-12;
    
    int n,R,T;
    struct Edge{
        int to,nxt;
    } e[80000];
    int head[410],ecnt;
    void AddEdge(int u,int v) {
        e[++ecnt]=(Edge){v,head[u]};
        head[u]=ecnt;
    }
    db p[410],sz[410],ans[11][11],f[510][210],g[2][2][510],s[2][510];
    // g[i][j][k] 在i拿球的情况下,j在第k次进球了
    db h[510][11][11][2];
    
    int main(){
        n=rd(),R=rd(),T=rd();
        rep(i,1,n*2) {
            scanf("%f",&p[i]);
            int e=rd(),f=rd();
            sz[i]=e+f+1;
            rep(j,1,e) {
                int x=rd();
                if(i>n) x+=n;
                AddEdge(i,x);
            }
            rep(j,1,f) {
                int x=rd();
                if(i<=n) x+=n;
                AddEdge(i,x);
            }
        }
        rep(d,0,1) {
            f[0][d*n+1]=1;
            rep(i,0,T) {
                rep(j,1,n*2) if(f[i][j]>eps) {
                    db t=f[i][j]/sz[j];
                    for(reg int k=head[j];k;k=e[k].nxt) f[i+1][e[k].to]+=t;
                    f[i+1][j>n?1:n+1]+=t*(1-p[j]);
                    g[d][j>n][i+1]+=t*p[j];
                    f[i][j]=0;
                }
            }
            rep(i,0,T) {
                s[d][i]=g[d][0][i]+g[d][1][i];
                if(i) s[d][i]+=s[d][i-1];
            }
        }
        h[0][0][0][0]=1;
        rep(i,0,T) {
            rep(a,0,R) rep(b,0,R) rep(j,0,1) if(h[i][a][b][j]>eps) {
                if(a==R || b==R || i==T){ ans[a][b]+=h[i][a][b][j]; continue; }
                rep(k,1,T-i) {
                    // 能在结束前产生一次进球
                    h[i+k][a+1][b][1]+=h[i][a][b][j]*g[j][0][k];
                    h[i+k][a][b+1][0]+=h[i][a][b][j]*g[j][1][k];
                }
                ans[a][b]+=h[i][a][b][j]*(1-s[j][T-i]);
            }
        }
        rep(i,0,R) rep(j,0,R) if(i<R || j<R) printf("%.10f
    ",ans[i][j]);
    }
    
    
    
    
  • 相关阅读:
    计算机病毒
    wordpress搬家教程
    javascript的DOM学习之选项卡制作
    javascript的DOM学习上
    [转]jQuery 引用地址{包括jquery和google提供的地址}, 节省你不必要的流量
    CSS3属性之:transition
    CSS3属性之:animastion
    css3学习系列之box-shadow(1)
    使ie678支持css3伪类选择器的插件
    个人网站名称填写注意事项
  • 原文地址:https://www.cnblogs.com/chasedeath/p/13591409.html
Copyright © 2020-2023  润新知