Atcoder-ABC291 "Teleporter and Closed off" 动态DP版
题目地址
题意:
在一个DAG图中,点 i 只有最多m条出边连向 i+1 ~ i+m(m<=10),边权均为1。对于
,依次输出当点k被删除时1到n的最短路。
分析:
标准做法无非就是预处理1到i的最短路和i到n的最短路,又由于题目性质,对于k我们只需对[k-10,k+10]遍历一下,顺着这个思路下去就能做出来了,复杂度为
我采取了动态dp去解决这道题(动态dp可参考博客)。
思路
我们设
当一个点被删除时,其状态矩阵的第一行全部被替换为无穷大(之后的代码中用rep
表示某点被删除后的新矩阵)。
由于每次都要获取从头到尾的dp值,所以根本不用拿线段树去维护区间矩阵乘积。我们预处理出前缀乘积和后缀乘积即可。
总复杂度为:
代码:
#include<bits/stdc++.h> using namespace std; using ll = long long; const int mod=998244353; const int maxn = 1e5+5; const ll inf = 1e9; int n,m; struct MT{ ll mt[10][10]; }ar[maxn],pre[maxn],suf[maxn]; MT operator*(const MT& a,const MT& b){ MT c; for(int i=0;i<m;++i) { for(int j=0;j<m;++j) { c.mt[i][j]=inf; for(int k=0;k<m;++k) { c.mt[i][j]=min(c.mt[i][j],a.mt[i][k]+b.mt[k][j]); } } } return c; } int main() { cin.tie(0)->sync_with_stdio(false); cin>>n>>m; for(int i=1;i<=n;++i){ string s; cin>>s; auto& mt=ar[i].mt; for(int i=0;i<m;++i) mt[0][i]=(s[i]=='0'? inf : 1); for(int i=1;i<m;++i) for(int j=0;j<m;++j) mt[i][j]=(i-1==j?0:inf); if(i==n) mt[0][0]=-inf; } MT ori,rep; for(int i=0;i<m;++i) for(int j=0;j<m;++j) ori.mt[i][j]=inf; rep=ar[1]; for(int i=0;i<m;++i) rep.mt[0][i]=inf; pre[1]=ar[1]; suf[n]=ar[n]; for(int i=2;i<=n;++i) pre[i]=pre[i-1]*ar[i]; for(int i=n-1;i>=1;--i) suf[i]=ar[i]*suf[i+1]; for(int i=2;i<=n-1;++i) { MT res=pre[i-1]*rep*suf[i+1]*ori; if(res.mt[0][0]>=inf) cout<<"-1 "; else cout<<res.mt[0][0]<<" "; } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App