• CF553E Kyoya and Train


    CF553E Kyoya and Train

    还是那句话,我觉得分治FFT是有实现难度的 初学,dalao别D

    看完题第一反应应该是设 (dp(i,j)) 表示时刻 (j) 到达点 (i) 的最小代价。

    发现完全不会处理边界,想了一会就舍掉了。

    (dp(i,j)) 表示时刻 (j)(i) 到达 (n) 的最小代价,那么答案就是 (dp(1,0))

    这个是可以转移的。

    [f(u,j)= egin{cases} (u=n) egin{cases} 0(jle t)\ x(jgt t)\ end{cases} \ (else) egin{cases} min{sum_{k=1}^{t} P_{(u,v),k}f(v,j+k)+w(u,v) } (jle t)\ dis(u,n)+x(jgt t)\ end{cases} end{cases} ]

    暴力是 (O(mt^2)) 的,倒序枚举 (t) 即可。

    然后就不会了。。。

    嗯,好,这个式子居然可以直接算出来,我只能爬,多项式nb。

    首先应当注意到 (sum_{k=1}^{t} P_{(u,v),k}f(v,j+k)) 是可以卷的,随便把一个多项式翻转就能卷了。

    问题在于我们必须知道所有 (j>i)(f(v,j)) 才能计算 (f(u,i)) ,如果暴力倒序枚举 (j) 复杂度又回去了。

    考虑分治FFT,这东西可以自己更新自己。应该先分治右区间再分治左区间。

    然而还是不会

    为啥不会算呢?仔细一想主要是复杂度不对,因为取 (min) ,每次必须把长度为 (t) 的多项式卷起来。

    然后我怎么就没想到搞一个可以直接加的东西出来哦/kk

    (g(i,j)) 表示 在 (j) 时刻开始走第 (i) 条边走到 (n) 的最短时间,那么 (f(a_i,j)=g(i,j))

    这个 (g(i,[l,mid])) 可以通过 (f(b_i,[mid+1,r])) 搞出来, 而且因为后半段的 (f) 已经确定,必然最优,直接相加没有错!

    递归到 (l=r) 的时候用 (g)(f) 更新掉就好了

    转移大概长这样:

    (钦定 (P_{i,0}=0)看着舒服)

    [g(i,x)=sum_{j=0}^{t}P_{i,j}f(b_i,x+j) ]

    用cdq分治的思路,不断统计右区间对左区间的贡献就能算出 (g) 了。

    然后就是非常烦的边界处理,一定想清楚再打,尽量不要调。但是我边界对了FFT打挂了是我没想到的

    (A_j=P_{i,j}(lle jle r),B_{r-j+mid+1}=f(b_i,r-j)(mid+1le r-jle r))

    (A,B) 卷起来看看是啥

    ([z^k]A*B=sum_{j=0}^{k}A_jB_{k-j}=sum _{j=0}^{k}P_{i,j}f(b_i,r-k+j))

    所以提取 (r-j) 这一项加到 (jin [l,mid]) 上即可。

    #include<bits/stdc++.h>
    using namespace std;
    #define fi first
    #define se second
    #define mkp(x,y) make_pair(x,y)
    #define pb(x) push_back(x)
    #define sz(v) (int)v.size()
    typedef long long LL;
    typedef double db;
    template<class T>bool ckmax(T&x,T y){return x<y?x=y,1:0;}
    template<class T>bool ckmin(T&x,T y){return x>y?x=y,1:0;}
    #define rep(i,x,y) for(int i=x,i##end=y;i<=i##end;++i)
    #define per(i,x,y) for(int i=x,i##end=y;i>=i##end;--i)
    inline int read(){
    	int x=0,f=1;char ch=getchar();
    	while(!isdigit(ch)){if(ch=='-')f=0;ch=getchar();}
    	while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
    	return f?x:-x;
    }
    const int V=55;
    const int E=105;
    const int N=20005;
    const int M=N<<2;
    const db inf=1e15;
    int n,m,t,X,a[E],b[E],c[E];
    db p[E][N<<1],dis[V][V],f[E][N<<1];
    
    namespace poly{
    
    const db PI=acos(-1.0);
    
    int rev[M],lg,lim;
    db g[E][N<<1];
    void init(const int&n){
    	for(lg=0,lim=1;lim<=n;++lg,lim<<=1);
    	for(int i=0;i<lim;++i)rev[i]=(rev[i>>1]>>1)|((i&1)<<(lg-1));
    }
    struct cp{
    	db x,y;
    	cp(){x=y=0;}
    	cp(db x_,db y_){x=x_,y=y_;}
    	cp operator + (const cp&t)const{return cp(x+t.x,y+t.y);}
    	cp operator - (const cp&t)const{return cp(x-t.x,y-t.y);}
    	cp operator * (const cp&t)const{return cp(x*t.x-y*t.y,x*t.y+y*t.x);}
    };
    void FFT(cp*a,int op){
    	for(int i=0;i<lim;++i)
    		if(i>rev[i])swap(a[i],a[rev[i]]);
    	for(int i=1;i<lim;i<<=1){
    		cp wn=cp(cos(PI/i),sin(PI/i)*(op?1:-1));
    		for(int j=0;j<lim;j+=i<<1){
    			cp w0=cp(1,0);
    			for(int k=0;k<i;++k,w0=w0*wn){
    				const cp X=a[j+k],Y=w0*a[i+j+k];
    				a[j+k]=X+Y,a[i+j+k]=X-Y;
    			}
    		}
    	}
    	if(op)return;
    	for(int i=0;i<lim;++i)a[i].x/=lim;
    }
    void CDQ_FFT(int l,int r){
    	if(l==t&&r==2*t-1)return;
    	static cp A[M],B[M];
    	if(l==r){
    		rep(i,1,n-1)f[i][l]=inf;
    		for(int i=1;i<=m;++i)if(a[i]!=n)ckmin(f[a[i]][l],g[i][l]+c[i]);
    		return;
    	}
    	int mid=(l+r)>>1;
    	CDQ_FFT(mid+1,r);
    	init(r-l+r-mid);
    	for(int i=1;i<=m;++i){
    		if(a[i]==n)continue;
    		for(int j=0;j<lim;++j)A[j]=B[j]=cp(0,0);
    		for(int j=0;j<=r-l;++j)A[j].x=p[i][j];
    		for(int j=mid+1;j<=r;++j)B[j-mid-1].x=f[b[i]][r-j+mid+1];
    		FFT(A,1),FFT(B,1);
    		for(int j=0;j<lim;++j)A[j]=A[j]*B[j];
    		FFT(A,0);
    		for(int j=l;j<=mid;++j)g[i][j]+=A[r-j].x;
    	}
    	CDQ_FFT(l,mid);
    }
    }
    signed main(){
    	n=read(),m=read(),t=read(),X=read();
    	rep(i,1,n)rep(j,1,n)dis[i][j]=i==j?0:inf;
    	for(int i=1;i<=m;++i){
    		a[i]=read(),b[i]=read(),c[i]=dis[a[i]][b[i]]=read();
    		rep(j,1,t)p[i][j]=1.*read()/100000;
    	}
    	rep(k,1,n)rep(i,1,n)rep(j,1,n)ckmin(dis[i][j],dis[i][k]+dis[k][j]);
    	rep(i,1,n-1)rep(j,t,t*2-1)f[i][j]=dis[i][n]+X;
    	rep(i,0,t*2-1)f[n][i]=i<=t?0:X;
    	poly::CDQ_FFT(0,t*2-1);
    	printf("%.9lf
    ",f[1][0]);
    	return 0;
    }
    
    
  • 相关阅读:
    2014年互联网发展趋势如何
    服务器出现阶段性错误
    用互联网思想武装自己
    杭州互联网公司汇总
    互联网牛人网址大全
    ffmpeg开发指南
    Windows下FFmpeg快速入门
    FFmpeg介绍及参数详细说明
    windows 下FFMPEG的编译方法 附2012-9-19发布的FFMPEG编译好的SDK下载
    FFMPEG视音频编解码零基础学习方法 【荐】
  • 原文地址:https://www.cnblogs.com/zzctommy/p/14209728.html
Copyright © 2020-2023  润新知