LP1979 NOIP2013 华容道

Author Avatar
空気浮遊 2018年10月29日
  • 在其它设备中阅读本文章
  • 最短路
  • 分享到 Facebook
  • 分享到 Telegram
  • 分享到 Twitter
  • 分享到微博

Problem

https://www.luogu.org/problemnew/show/P1979

Solution

朴素算法是 $O(qn^4)$ 的 BFS,能过约 80 分。

考虑若目标棋子需要移动,则空白格子一定与目标棋子相邻。

因此设计状态 $(x, y, g)$,表示空白棋子与目标棋子 $(x, y)$ 相邻的的方向。

预处理 $(x, y, g_1, g_2)$,代表状态 $(x, y, g_1)$ 到 $(x, y, g_2)$ 的最少步数。

查询时先 BFS 到达与目标棋子相邻的状态,再 SPFA 在该状态上最短路即可。

为什么用 SPFA?

因为当年 SPFA 还没死(逃

理论复杂度 $O(4n^4+qn^3)$

Code

// Code by ajcxsu
// Problem: chess road

#include<bits/stdc++.h>
#define CLR(x, y) memset(x, y, sizeof(x))
using namespace std;

const int N=31;
int mp[N][N];
int e[N][N][4][4];
int dist[N][N][4];
char S[N][N][4];

int mv[]={0, 1, 0, -1, 0};
int opp[]={2, 3, 0, 1};
int n, m;
bool valid(int x, int y) { return x>=1 && x<=n && y>=1 && y<=m && mp[x][y]; }
struct Dot { int x, y, g; } ;
queue<Dot> qu;
int dis[N][N];
void bfs(int x, int y, int g) {
    CLR(dis, 0x3f);
    if(!valid(x+mv[g], y+mv[g+1])) return;
    mp[x][y]=0;
    qu.push({x+mv[g], y+mv[g+1]});
    dis[x+mv[g]][y+mv[g+1]]=0;
    Dot na;
    int nx, ny;
    while(!qu.empty()) {
        na=qu.front(), qu.pop();
        for(int i=0;i<4;i++) {
            nx=na.x+mv[i], ny=na.y+mv[i+1];
            if(valid(nx, ny) && dis[nx][ny]>dis[na.x][na.y]+1) {
                dis[nx][ny]=dis[na.x][na.y]+1;
                qu.push({nx, ny});
            }
        }
    }
    for(int i=0;i<4;i++)
        e[x][y][g][i]=dis[x+mv[i]][y+mv[i+1]];
    mp[x][y]=1;
}

int SPFA(int sx, int sy, int ex, int ey, int tx, int ty) {
    if(ex==tx && ey==ty) return 0;
    CLR(dist, 0x3f);
    CLR(dis, 0x3f);
    mp[ex][ey]=0;
    qu.push({sx, sy});
    dis[sx][sy]=0;
    Dot na;
    int nx, ny, ng;
    while(!qu.empty()) {
        na=qu.front(), qu.pop();
        for(int i=0;i<4;i++) {
            nx=na.x+mv[i], ny=na.y+mv[i+1];
            if(valid(nx, ny) && dis[nx][ny]>dis[na.x][na.y]+1) {
                dis[nx][ny]=dis[na.x][na.y]+1;
                qu.push({nx, ny});
            }
        }
    }
    mp[ex][ey]=1;
    for(int i=0;i<4;i++) if(valid(ex+mv[i], ey+mv[i+1])) {
        dist[ex][ey][i]=dis[ex+mv[i]][ey+mv[i+1]], qu.push({ex, ey, i}),
        S[ex][ey][i]=1;
    }
    while(!qu.empty()) {
        na=qu.front(), qu.pop(); S[na.x][na.y][na.g]=0;
        for(int i=0;i<4;i++) {
            nx=na.x+mv[i], ny=na.y+mv[i+1], ng=opp[i];
            if(valid(nx, ny) && dist[nx][ny][ng]>dist[na.x][na.y][na.g]+e[na.x][na.y][na.g][i]+1) {
                dist[nx][ny][ng]=dist[na.x][na.y][na.g]+e[na.x][na.y][na.g][i]+1;
                if(!S[nx][ny][ng]) qu.push({nx, ny, ng});
            }
        }
    }
    int ans=0x3f3f3f3f;
    for(int i=0;i<4;i++) ans=min(ans, dist[tx][ty][i]);
    return ans;
}

int main() {
    CLR(e, 0x3f);
    ios::sync_with_stdio(false), cin.tie(0);
    int q;
    cin>>n>>m>>q;
    for(int i=1;i<=n;i++)
    for(int j=1;j<=m;j++) cin>>mp[i][j];
    for(int i=1;i<=n;i++)
    for(int j=1;j<=m;j++) if(mp[i][j])
        for(int k=0;k<4;k++) bfs(i, j, k);
    int a, b, c, d, e, f, res;
    while(q--) {
        cin>>a>>b>>c>>d>>e>>f;
        cout<<((res=SPFA(a, b, c, d, e, f))==0x3f3f3f3f?-1:res)<<endl;
    }
    return 0;
}

本文链接:https://pst.iorinn.moe/archives/sol-luogu-1979.html
许可: https://pst.iorinn.moe/license.html
若无特别说明,博客内的文章默认将采用 CC BY 4.0 许可协议 进行许可☆

      新篇
旧篇      
    • fingerprint Login
  • home 主页
  • inbox 归档
    • June 2026 1
    • December 2024 1
    • August 2024 1
    • June 2024 1
    • April 2024 3
    • March 2024 1
    • February 2024 2
    • January 2024 1
    • November 2023 1
    • August 2023 1
    • May 2023 1
    • February 2023 2
    • January 2023 2
    • July 2022 1
    • June 2022 1
    • April 2022 1
    • March 2022 1
    • February 2022 2
    • December 2021 1
    • November 2021 1
    • August 2021 3
    • July 2021 3
    • April 2021 2
    • March 2021 1
    • February 2021 4
    • January 2021 2
    • December 2020 1
    • November 2020 1
    • October 2020 3
    • September 2020 1
    • August 2020 1
    • July 2020 1
    • March 2020 1
    • December 2019 1
    • September 2019 1
    • July 2019 1
    • April 2019 2
    • March 2019 13
    • February 2019 15
    • January 2019 11
    • December 2018 3
    • November 2018 6
    • October 2018 28
    • September 2018 31
    • August 2018 18
    • July 2018 13
    • June 2018 27
    • May 2018 11
    • April 2018 12
    • March 2018 19
    • February 2018 8
    • January 2018 7
    • December 2017 2
    • November 2017 2
  • apps 分类
    • 笔记
    • 题解
    • 杂文
    • 技术
    • 游戏
    • 小说
  • 留言板
  • 关于
  • 友链
  • 文章总数 281
主题 - Material i
expand_less
Copyright © 2026 雪屋
Float in air.
Powered by Typecho
Theme - Material