P3645 [APIO2015]雅加达的摩天楼
2021/7/15 23:37:59
本文主要是介绍P3645 [APIO2015]雅加达的摩天楼,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
根号分治,跳跃能力小于等于 \(\sqrt N\) 的 doge 不同跳跃能力数量有限,大于 \(\sqrt N\) 的 doge 能跳到的位置有限。
所以状态只有 \(O((N+M)\sqrt N)\) 种,可以接受,用 bitset
判断是否出现比较方便。
然后有一种神奇的东西叫 01BFS,能 \(O(V+E)\) 解决边权仅为 \(0\) 和 \(1\) 的最短路问题。
当选择一条权值为 \(0\) 的边时,塞入队首;当选择一条权值为 \(0\) 的边时,塞入队尾。这样能时刻维护队列的单调性。
值得注意的是,因为本题的特殊性,同一座摩天楼会在不同的跳跃能力下多次入队。但传递消息是不需要花跳跃次数的,所以在一个点拓展完后,就不需要再次拓展了,否则枚举出边的复杂度会退化为 \(O(VE)\)。
还有一个极易忽略的点(建议去 UOJ 上交一发),01BFS 要在出队时打标记而不是入队时,因为有可能第一次是塞入队尾,后面塞入队首可能跳跃次数更少。这样时间复杂度并不会改变,因为仅仅是在 \(O(E)\) 的前提下多塞入了一些点,这些点不会进行拓展。
code:
#include<bits/stdc++.h> using namespace std; #define N 30005 #define For(i,x,y)for(i=x;i<=(y);i++) bitset<N>k[N]; deque<int>tim; vector<int>vec[N]; deque<pair<int,int> >deq; int main() { pair<int,int>pa; int n,m,i,b,p,tmp; scanf("%d%d",&n,&m); For(i,0,m-1) { scanf("%d%d",&b,&p); vec[b].push_back(p); if(!i)deq.push_back(make_pair(b,p)); if(i==1)pa=make_pair(b,p); } tim.push_back(0); while(!deq.empty()) { b=deq.front().first; p=deq.front().second; tmp=tim.front(); if(make_pair(b,p)==pa)break; deq.pop_front(); tim.pop_front(); if(k[b][p])continue; k[b][p]=1; if(b>=p)deq.push_back(make_pair(b-p,p)),tim.push_back(tmp+1); if(b+p<n)deq.push_back(make_pair(b+p,p)),tim.push_back(tmp+1); while(!vec[b].empty()) { if(!k[b][vec[b].back()])deq.push_front(make_pair(b,vec[b].back())),tim.push_front(tmp); vec[b].pop_back(); } } printf("%d",(deq.empty()?-1:tmp)); return 0; }
这篇关于P3645 [APIO2015]雅加达的摩天楼的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-12-28一步到位:购买适合 SEO 的域名全攻略
- 2024-12-27OpenFeign服务间调用学习入门
- 2024-12-27OpenFeign服务间调用学习入门
- 2024-12-27OpenFeign学习入门:轻松掌握微服务通信
- 2024-12-27OpenFeign学习入门:轻松掌握微服务间的HTTP请求
- 2024-12-27JDK17新特性学习入门:简洁教程带你轻松上手
- 2024-12-27JMeter传递token学习入门教程
- 2024-12-27JMeter压测学习入门指南
- 2024-12-27JWT单点登录学习入门指南
- 2024-12-27JWT单点登录原理学习入门