#根号分治#洛谷 3645 [APIO2015]雅加达的摩天楼

题目传送门


分析

\(d[i][j]\) 表示 所处位置为 \(i\),跳跃能力为 \(j\) 的步数,
\(j\leq \sqrt{n}\),这样的状态最多有 \(n\sqrt{n}\) 个,
\(j>\sqrt{n}\),这样的状态最多有 \(m\sqrt{n}\) 个。
所以最多有 \((n+m)\sqrt{n}\) 个状态,用 \(bitset\) 维护是否走过即可


代码

#include <cstdio>
#include <cctype>
#include <bitset>
#include <queue>
#include <vector>
#define rr register
using namespace std;
const int N=30011;
struct rec{int x,y,z;}; queue<rec>q;
bool unvis[N]; bitset<N>v[N];
vector<int>K[N]; int n,S,T;
inline signed iut(){
	rr int ans=0; rr char c=getchar();
	while (!isdigit(c)) c=getchar();
	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
	return ans;
}
inline void print(int ans){
	if (ans>9) print(ans/10);
	putchar(ans%10+48);
}
inline void Insert(int x,int y,int z){
	if (!unvis[x]){
		unvis[x]=1;
		rr int siz=K[x].size();
		for (rr int i=0;i<siz;++i){
			rr int t=K[x][i];
			if (!v[x][t]) v[x][t]=1,q.push((rec){x,t,z});
		}
	}
	if (!v[x][y]) v[x][y]=1,q.push((rec){x,y,z});
}
signed main(){
	n=iut();
	for (rr int Y=iut();Y;--Y){
		rr int x=iut()+1,y=iut();
		if (S&&!T) T=x;
		if (!S) S=x;
		K[x].push_back(y);
	}
    if (S==T) return !printf("0");
    Insert(S,30001,0);
	while (!q.empty()){
		rr rec t=q.front(); q.pop();
		if (t.x-t.y==T||t.x+t.y==T)
		    return !printf("%d",t.z+1);
		if (t.x-t.y>0) Insert(t.x-t.y,t.y,t.z+1);
		if (t.x+t.y<=n) Insert(t.x+t.y,t.y,t.z+1);
	}	
	return !printf("-1");
}
posted @ 2021-10-19 16:32  lemondinosaur  阅读(39)  评论(0编辑  收藏  举报