「NOI2020」美食家 题解 (矩阵优化DP)
题目简介
有 个结点, 条单向边。到达第 个结点即可获得权值 。第 条单向边由 连向 ,通过这条边需要 个时间。
又有 个事件,第 个事件规定在 时刻结点 的权值会变成 。
现在共 个时间,你需要在第 天从结点 出发,第 天回到结点 ,中途不做停留。问最终你能获得的最大权值为多少。
,,,
,,,
分析
最朴素,最容易想到(好像本蒟蒻并没有想到)的 是:
这里 表示到达花费 个时间到达结点 的最大权值。 表示第 时刻 结点附加的权值。
接着你看, 不大,这又是个图论题,那么多半都是矩阵优化了。
将 视作一个矩阵,我们需要构造一个合适的矩阵 ,使得
根据本题目特性,我们将这里的矩阵乘法定义为:
但是问题是,平日里鄙人所见过的那些宛如沧海一粟的题目中,只需要填 就行了,每乘一次就是转移一条边。但是如今如果贸然填 的话,就直接忽略了题目中 的限制 ,应当怎么转换呢?
实际上,在这 天中途,我们可以看作是到达了一个没有权值的结点,所以我们只需要一条边拆成 条边(这个理解方法有很多,也可以看作拆点)即可。将前 条边权值赋为 ,将第 条赋值为 。具体实现是多加一些点,可以看代码。
我们在 个相邻的事件间,用 ,再令 即可。
然后就 了……
会发现这个算法的时间复杂度是 的。
可以进行二进制拆分,先需处理出 ,将总时间复杂度优化为
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
using ll=long long;
int c[55];
int id[515][8],tot;
struct matrix{
ll mat[255][255];
matrix(){memset(mat,0xcf,sizeof mat);}
ll* operator[](int x){return mat[x];}
matrix operator*(matrix& b){
matrix c;
for(int i=1;i<=tot;++i)
for(int j=1;j<=tot;++j)
for(int k=1;k<=tot;++k)
c[i][j]=max(c[i][j],mat[i][k]+b[k][j]);
return c;
}
}g[32];
struct event{
int t,x,y;
bool operator<(const event& sec)const{return t<sec.t;}
}a[255];
ll ans[255];
ll tmp[255];
void mul(int p){
for(int i=1;i<=tot;++i)tmp[i]=-1e18;
for(int i=1;i<=tot;++i)
for(int j=1;j<=tot;++j)
tmp[j]=max(tmp[j],1ll*(ans[i]+g[p][i][j]));
for(int i=1;i<=tot;++i)ans[i]=tmp[i];
}
int main(){
int n,m,T,K;cin>>n>>m>>T>>K;
for(int i=1;i<=n;++i)cin>>c[i];
for(int i=1;i<=n;++i)id[i][0]=++tot;
for(int i=1;i<=m;++i){
int x,y,z;cin>>x>>y>>z;
for(int j=1;j<z;++j)if(!id[x][j])id[x][j]=++tot;
for(int j=1;j<z;++j)g[0][id[x][j-1]][id[x][j]]=0;
g[0][id[x][z-1]][y]=c[y];
}
for(int i=1;i<=K;++i)cin>>a[i].t>>a[i].x>>a[i].y;
sort(a+1,a+K+1);
for(int i=1;i<=30;++i)g[i]=g[i-1]*g[i-1];
ans[1]=c[1];
for(int i=2;i<=tot;++i)ans[i]=-1e18;
a[K+1].t=T;
for(int i=1;i<=K+1;++i){
int d=a[i].t-a[i-1].t;
for(int j=30;~j;--j)if((d>>j)&1)mul(j);
ans[a[i].x]+=a[i].y;
}
if(ans[1]>=0)cout<<ans[1]<<'\n';
else cout<<-1<<'\n';
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现