Luogu P6772 [NOI2020] 美食家

题链

分析

好水的T1

和动态DP一个套路的矩阵乘法优化

然后倍增预处理出矩阵乘法的结果,每次用向量乘上矩阵

#include<bits/stdc++.h>
#define ll long long
const ll INF=1e18;
using namespace std;

const int N=255,M=55;
int n,m,T,K,c[N];
ll f[6][N][N],g[31][N][N],ans[N];
struct A{int t,x,y; }a[N];
bool cmp(A i,A j) {
	return i.t<j.t;
}
void mul(ll a[][N],ll b[][N],int n) {
	for(int i=1;i<=n;i++) {
		for(int j=1;j<=n;j++) {
			for(int k=1;k<=n;k++) {
				b[i][j]=max(b[i][j],a[i][k]+a[k][j]);
			}
		}
	}
}
void mul2(ll *a,ll b[][N],int n) {
	static ll tmp[N];
	memcpy(tmp,a,sizeof(tmp));
	for(int i=1;i<=n;i++) {
		a[i]=-INF;
		for(int j=1;j<=n;j++) {
			a[i]=max(a[i],tmp[j]+b[j][i]);
		}
	}
}
int main() {
	scanf("%d%d%d%d",&n,&m,&T,&K);
	for(int i=1;i<=n;i++) {
		scanf("%d",&c[i]);
	}
	for(int i=0;i<=5;i++) {
		for(int j=1;j<=n;j++) {
			for(int k=1;k<=n;k++) {
				f[i][j][k]=-INF;
			}
		}
	}
	for(int i=1;i<=n;i++) f[0][i][i]=0;
	for(int i=1;i<=m;i++) {
		int u,v,k; scanf("%d%d%d",&u,&v,&k);
		f[k][u][v]=c[v];
	}
	for(int i=1;i<=5;i++) {
		for(int j=1;i+j<=5;j++) {
			for(int k=1;k<=n;k++) {
				for(int l=1;l<=n;l++) {
					for(int x=1;x<=n;x++) {
						f[i+j][k][l]=max(f[i+j][k][l],f[i][k][x]+f[j][x][l]);
					}
				}
			}
		}
	}
	for(int i=1;i<=n;i++) {
		for(int j=0;j<5;j++) {
			for(int k=1;k<=n;k++) {
				for(int l=0;l<5;l++) {
					if(j-l+1>=0) {
						g[0][i+j*n][k+l*n]=f[j-l+1][i][k];
					} else g[0][i+j*n][k+l*n]=-INF;
				}
			}
		}
	}
	for(int i=1,len=2;len<=T;len<<=1,i++) {
		for(int j=1;j<=5*n;j++) {
			for(int k=1;k<=5*n;k++) g[i][j][k]=-INF;
		}
		mul(g[i-1],g[i],5*n);
	}
	for(int i=1;i<=K;i++) {
		scanf("%d%d%d",&a[i].t,&a[i].x,&a[i].y);
	}
	sort(a+1,a+K+1,cmp);
	if(a[K].t<T) a[K+1].t=T,K++;
	for(int i=1;i<=5*n;i++) ans[i]=-INF;
	ans[1]=c[1];
	for(int i=1;i<=K;i++) {
		for(int j=0;j<30;j++) {
			if((a[i].t-a[i-1].t)&(1<<j)) {
				mul2(ans,g[j],5*n);
			} 
		}
		if(a[i].x) ans[a[i].x]+=a[i].y;
	}
	if(ans[1]<0) cout<<-1<<endl;
		else cout<<ans[1]<<endl; 
	return 0;
}
posted @ 2021-06-22 23:44  wwwsfff  阅读(80)  评论(0编辑  收藏  举报