Luogu P6772 [NOI2020] 美食家
Posted wwwsfff
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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;
}
以上是关于Luogu P6772 [NOI2020] 美食家的主要内容,如果未能解决你的问题,请参考以下文章