1 条题解

  • 0
    @ 2025-8-24 22:55:59

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar Add_Catalyst
    喵哇喵

    搬运于2025-08-24 22:55:59,当前版本为作者最后更新于2024-05-12 18:20:17,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    P10232 [COCI 2023/2024 #4] Roboti 题解


    知识点

    简单环,DFS。


    题意分析

    nn 行,mm 列的网格里,给定 kk 个转弯点,再给定 QQ 个询问,问每次从某个坐标到另一个坐标的最少转弯次数,或者判断不可能到达。


    思路分析

    我们发现在一个点坐标与方向确定的时候,到达的下一个点的坐标与方向一定确定,那我们把每个转弯点拆成四个方向不同的点,分别判断,那么整个图就变成了一堆简单环,那么两个点的距离就很容易得到,判断合法也只要看是不是在一个环里即可。


    CODE

    #include<bits/stdc++.h>
    #define Fi first
    #define Se second
    #define endl '\n'
    #define INF 0x3f3f3f3f
    #define Pii pair<int,int>
    #define All(a) begin(a),end(a)
    #define tomax(a,b) ((a)=max((a),(b)))
    #define tomin(a,b) ((a)=min((a),(b)))
    #define FOR(i,a,b) for(register int i=(a);i<=(b);++i)
    #define DOR(i,a,b) for(register int i=(a);i>=(b);--i)
    #define main Main();signed main(){ios::sync_with_stdio(0);cin.tie(0);return Main();}signed Main
    using namespace std;
    constexpr int N=1e5+10,M=1e6+10,dx[4]={0,1,0,-1},dy[4]={1,0,-1,0};
    bool ti[N];
    bool vis[N][4];
    int n,m,k,Q,cnt;
    int x[N],y[N],siz[N<<2];
    int id[N][4],dep[N][4];
    Pii p[4][2],fa[N][4];
    vector< Pii > X[M],Y[M];
    int nxt(int x,int y,int d){
    	Pii cur={d&1?x:y,d<2?INF:0};
    	auto it=d&1?lower_bound(All(Y[y]),cur):lower_bound(All(X[x]),cur);
    	auto it1=d&1?Y[y].begin():X[x].begin(),it2=d&1?Y[y].end():X[x].end();
    	if(d<2)swap(it1,it2);
    	if(it==it1)it=it2;
    	if(it==it1)return -1;
    	if(d>1)--it;
    	return it->Se;
    }
    void dfs(int u,int d){
    	Pii v=fa[u][d];
    	vis[u][d]=1,id[u][d]=cnt,++siz[cnt];
    	if(~v.Fi&&!vis[v.Fi][v.Se])dep[v.Fi][v.Se]=dep[u][d]+1,dfs(v.Fi,v.Se);
    }
    int dis(Pii a,Pii b){
    	if(id[a.Fi][a.Se]!=id[b.Fi][b.Se])return INF;
    	return (dep[b.Fi][b.Se]-dep[a.Fi][a.Se]+siz[id[a.Fi][a.Se]])%siz[id[a.Fi][a.Se]];
    }
    signed main(){
    	cin>>n>>m>>k;
    	FOR(i,1,k){
    		char c;
    		cin>>x[i]>>y[i]>>c,ti[i]=(c=='L'),X[x[i]].push_back({y[i],i}),Y[y[i]].push_back({x[i],i});
    	}
    	FOR(i,1,n)sort(All(X[i]));
    	FOR(i,1,m)sort(All(Y[i]));
    	FOR(i,1,k)FOR(d,0,3){
    		int _d=ti[i]?(d+3)%4:(d+1)%4;
    		fa[i][d]={nxt(x[i],y[i],_d),_d};
    	}
    	FOR(i,1,k)FOR(d,0,3)if(!vis[i][d])++cnt,dfs(i,d);
    	cin>>Q;
    	while(Q--){
    		int xa,ya,xb,yb,ans=INF;cin>>xa>>ya>>xb>>yb;
    		FOR(d,0,3)p[d][0]={nxt(xa,ya,d),d},p[d][1]={nxt(xb-dx[d],yb-dy[d],d),d};
    		FOR(d,0,3)if(~p[d][0].Fi)FOR(_d,0,3)if(~p[_d][1].Fi)tomin(ans,dis(p[d][0],p[_d][1]));
    		if(xa==xb&&X[xa].empty()||ya==yb&&Y[ya].empty())ans=0;
    		cout<<(ans<INF?ans:-1)<<endl;
    	}
    	return 0;
    }
    /*
    首先,拆点,把每个转折点拆成 4 个方向,然后我们发现,如果一个点有出入度,那么必定是一个出度和一个入度,
    所以问题就转化为了一堆简单环上判断距离,直接求解即可。
    */
    

    • 1

    信息

    ID
    9882
    时间
    2000ms
    内存
    512MiB
    难度
    5
    标签
    递交数
    0
    已通过
    0
    上传者