zoukankan      html  css  js  c++  java
  • 洛谷 P6772

    NOI 签到题我都不会哦~

    洛谷题目页面传送门

    题意见洛谷。(以下用 (K) 表示 (k) 以避免与迭代变量冲突)

    首先有个很显然的 DP:(dp_{i,j}) 表示第 (i) 天小 W 在城市 (j) 的情况下获得的最大愉悦值之和。边界:(dp_{0,i}=egin{cases}c_1&i=1\-infty&i eq1end{cases});目标:(dp_{T,1});状态转移方程:

    [dp_{i,j}=max_{(k,j,len)in E}{dp_{i-len,k}+c_j+ext(i,j)} ]

    其中 (ext(i,j)) 表示第 (i) 天城市 (j) 通过美食节额外获得的愉悦值。

    暴力 DP 肯定是不行的。这个 (T) 这么大,一脸矩阵快速幂的样子。

    考虑用矩阵的形式将状态转移方程写出来。我们重定义矩阵乘法,将 ( imes) 改为 (+),将 (+) 改为 (max),学过 DDP 的都知道这样满足原矩阵乘法的一切性质(我没学过 DDP 都知道)。需要注意的是,这种乘法意义下的单位元是

    [I=egin{bmatrix}0&-infty&-infty &cdots&-infty\-infty&0&-infty&cdots&-infty\-infty&-infty&0&cdots&-infty\vdots&vdots&vdots&ddots&-infty\-infty&-infty&-infty&-infty&0end{bmatrix} ]

    具体广义乘法这套理论等到我学 DDP 再研究吧。于是:

    [egin{bmatrix}dp_{i,1}&dp_{i,2}&cdots&dp_{i,n}&cdots&dp_{i-4,n}end{bmatrix}Delta_i=egin{bmatrix}dp_{i+1,1}&dp_{i+1,2}&cdots&dp_{i+1,n}&cdots&dp_{i-3,n}end{bmatrix} ]

    其中 (Delta) 是啥就不详细说了,大概就是前 (n) 列是转移方程里的 (c_j+ext(i,j))(如果转移不到就是 (-infty)),后 (4n) 列是一些 (0)(-infty) 表示移位。

    注意到大多数时候 (ext(i,j)=0),只存在 (mathrm O(K))(i) 使得不等于零。而所有 (ext) 为零的时候的 (Delta) 是相等的,于是考虑按有美食节的时间分段,每段快速幂,有美食节的时间暴力修改矩阵单独转移。

    这样复杂度为 (mathrm O!left(KN^3log T ight)),其中 (N=5n)。显然过不去,瓶颈在于快速幂。

    如何优化呢?注意到这里是同底数幂,想到进制光速幂,即设一个 (x) 进制,预处理出 (Delta^0,Delta^{x^y},cdots,Delta^{x^y(x-1)}),其中 (yin[0,lceillog_xT ceil]),然后每次算幂的时候将指数 (x) 进制拆分乘即可。时间复杂度 (mathrm O!left(N^3xlog_xT+KN^3log_xT ight))。本来就卡的很紧,似乎并没啥卵用。

    但是!这样一来,算幂的时候每次乘法(共 (mathrm O(log_xT)) 次)可以利用矩阵乘法的结合律,将矩阵乘到向量上去,时间复杂度 (mathrm O(N^2))!然鹅直接使用快速幂的话,一次快速幂是一个整体,无法在其过程中乘以向量;光速幂的优点是,它将乘的过程拆开了。

    总时间复杂度 (mathrm O!left(N^3xlog_xT+KN^2log_xT ight))。xjb 取个 (x=2) 即可得到 (mathrm O!left(N^3log T+KN^2log T ight)) 的复杂度。由于矩阵乘法常数非常小,可以通过。

    这里「xjb 取个 (x=2)」,换句话说就是光速幂的优化的地方不在「光速」,而在用矩阵乘法的结合律降低单次乘法的复杂度,这大概是个矩阵乘法比较惯用的套路吧。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    #define pb push_back
    #define mp make_pair
    #define X first
    #define Y second
    const int inf=0x3f3f3f3f3f3f3f3f;
    const int N=50,T=200,LOG_T=32; 
    int n,m,s,t;
    int c[N+1];
    vector<pair<int,int> > rnei[N+1];
    pair<int,pair<int,int> > spc[T+2];
    struct matrix{
    	int a[5*N][5*N];
    	int *operator[](int x){return a[x];}
    	matrix(){
    		for(int i=0;i<5*N;i++)for(int j=0;j<5*N;j++)a[i][j]=i==j?0:-inf;
    	}
    	friend matrix operator*(matrix x,matrix y){
    		matrix res;
    		for(int i=0;i<5*n;i++)for(int j=0;j<5*n;j++)res[i][j]=-inf;
    		for(int i=0;i<5*n;i++)for(int j=0;j<5*n;j++)for(int k=0;k<5*n;k++)
    			res[i][j]=max(res[i][j],x[i][k]+y[k][j]);
    		return res;
    	}
    	friend vector<int> operator*(vector<int> x,matrix y){
    		vector<int> res(5*n,-inf);
    		for(int j=0;j<5*n;j++)for(int k=0;k<5*n;k++)
    			res[j]=max(res[j],x[k]+y[k][j]);
    		return res;
    	}
    };
    matrix pw[LOG_T];
    vector<int> dp;
    signed main(){
    	cin>>n>>m>>s>>t;
    	for(int i=1;i<=n;i++)cin>>c[i];
    	while(m--){
    		int x,y,z;
    		cin>>x>>y>>z;
    		rnei[y].pb(mp(x,z));
    	}
    	for(int i=1;i<=t;i++)cin>>spc[i].X>>spc[i].Y.X>>spc[i].Y.Y;
    	for(int i=0;i<5*n;i++)for(int j=0;j<5*n;j++)pw[0][i][j]=-inf;
    	for(int i=1;i<=n;i++)for(int j=0;j<rnei[i].size();j++)
    		pw[0][(rnei[i][j].Y-1)*n+rnei[i][j].X-1][i-1]=c[i];
    	for(int i=n;i<5*n;i++)pw[0][i-n][i]=0;
    	for(int i=1;i<LOG_T;i++)pw[i]=pw[i-1]*pw[i-1];
    	sort(spc+1,spc+t+1);
    	spc[++t]=mp(inf,mp(0,0));
    	dp.resize(5*n,-inf);dp[0]=c[1];
    	for(int i=1;i<=t;i++){
    		if(spc[i].X>s){
    			int e=s-spc[i-1].X;
    			for(int j=0;j<LOG_T;j++)if(e&1<<j)dp=dp*pw[j];
    			break;
    		}
    		int e=spc[i].X-1-spc[i-1].X;
    		for(int j=0;j<LOG_T;j++)if(e&1<<j)dp=dp*pw[j];
    		matrix delta=pw[0];
    		for(int j=0;j<5*n;j++)delta[j][spc[i].Y.X-1]+=spc[i].Y.Y;
    		dp=dp*delta;
    	}
    	if(dp[0]<0)puts("-1");
    	else cout<<dp[0];
    	return 0;
    }
    
    珍爱生命,远离抄袭!
  • 相关阅读:
    【转】iOS深入学习(Block全面分析)
    iOS—请求Web Service
    iOS设计模式——MVC
    iOS基础知识
    iOS学习——常用博客
    【转】使用segue页面间传递数据
    【转】storyboard之 prepareForSegue:sender:
    【转】NSDictionary和NSMutableDictionary用法详解
    配置.pch文件
    MKNetworkKit下载图片并显示在UIImageView上
  • 原文地址:https://www.cnblogs.com/ycx-akioi/p/Luogu-P6772.html
Copyright © 2011-2022 走看看