Atcoder-ABC-431-E

网格图转向最短路问题

题目描述

给定一个 \(n \times m\) 的网格,每个格子标记为 ABC 类型。从起点 \((1, 1)\) 出发,初始方向向右,目标到达 \((n, m+1)\)(网格右侧外一格)且方向向右。

在不同的格子类型中转向有不同的代价规则:

  • A 格:直行不消耗代价,左右转消耗 1
  • B 格:左转不消耗代价,直行和右转消耗 1
  • C 格:右转不消耗代价,直行和左转消耗 1

求从起点到终点的最小总代价

输入格式

多组测试数据,每组包含:

  • 网格大小 \(n, m\)
  • \(n \times m\) 的网格,每个格子为 ABC

输出格式

每组数据输出一个整数,表示最小代价。

算法思路

状态设计

使用三元组 \((x, y, direction)\) 表示状态:

  • \((x, y)\):当前坐标
  • \(direction\):当前朝向(1→右,2↑上,3↓下,4←左)

核心算法:Dijkstra(优先队列 BFS)

由于转向代价不同,使用 Dijkstra 算法求最短路。

方向编码

1: → (右)
2: ↑ (上)
3: ↓ (下)
4: ← (左)

CODE

#include<bits/stdc++.h>
#define wk(x) write(x),putchar(' ')
#define wh(x) write(x),putchar('\n')
#define int long long
#define INF 2147483647
#define mod 998244353
#define N 610005
#define NO printf("No\n")
#define YES printf("Yes\n")




using namespace std;
int n,m,k,jk,ans,sum,num,cnt,tot;
int dis[N],vis[N][5],f[N];
char a[N];




void read(int &x){
    x=0;int ff=1;char ty;
    ty=getchar();
    while(!(ty>='0'&&ty<='9')){
        if(ty=='-') ff=-1;
        ty=getchar();
    }
    while(ty>='0'&&ty<='9')
        x=(x<<3)+(x<<1)+ty-'0',ty=getchar();
    x*=ff;return;
}




void write(int x){
    if(x==0){
        putchar('0');
        return;
    }
    if(x<0){
        x=-x;
        putchar('-');
    }
    char asd[201];int ip=0;
    while(x) asd[++ip]=x%10+'0',x/=10;
    for(int i=ip;i>=1;i--) putchar(asd[i]);
    return;
}




struct Q{
    int sum,x,y,fx;
    bool operator<(const Q&A)const{
        return A.sum<sum;
    }
};




priority_queue<Q> q;
/*
1:->
2:^
3:v
4:<- 
*/
int pd(int x,int fx){
    if(x==1){
        return fx;
    }else if(x==2){
        if(fx==1) return 3;
        if(fx==2) return 4;
        if(fx==3) return 1;
        if(fx==4) return 2;
    }else{
        if(fx==1) return 2;
        if(fx==2) return 1;
        if(fx==3) return 4;
        if(fx==4) return 3;
    }return 0;
}




pair<int,int> G(int x,int y,int fx){
    if(fx==1) return {x,y+1};
    if(fx==2) return {x-1,y};
    if(fx==3) return {x+1,y};
    if(fx==4) return {x,y-1};
    return {0,0};
}




void bfs(){
    while(!q.empty()) q.pop();
    q.push((Q){0,1,1,1});
    while(!q.empty()){
        Q A=q.top();q.pop();//wk(A.x),wk(A.y);wh(A.sum);
        if(A.x==n&&A.y==m+1&&A.fx==1) {ans=A.sum;return;}
        if(A.x<1||A.y<1||A.x>n||A.y>m||vis[A.x*m+A.y][A.fx]!=2e9) continue;
        vis[A.x*m+A.y][A.fx]=A.sum;
        if(a[A.x*m+A.y]=='A'){
            pair<int,int> to=G(A.x,A.y,pd(1,A.fx));
            if(vis[to.first*m+to.second][pd(1,A.fx)]==2e9) q.push((Q){A.sum,to.first,to.second,pd(1,A.fx)});
            to=G(A.x,A.y,pd(2,A.fx));
            if(vis[to.first*m+to.second][pd(2,A.fx)]==2e9) q.push((Q){A.sum+1,to.first,to.second,pd(2,A.fx)});
            to=G(A.x,A.y,pd(3,A.fx));
            if(vis[to.first*m+to.second][pd(3,A.fx)]==2e9) q.push((Q){A.sum+1,to.first,to.second,pd(3,A.fx)});
        }else if(a[A.x*m+A.y]=='B'){
            pair<int,int> to=G(A.x,A.y,pd(2,A.fx));
            if(vis[to.first*m+to.second][pd(2,A.fx)]==2e9) q.push((Q){A.sum,to.first,to.second,pd(2,A.fx)});
            to=G(A.x,A.y,pd(1,A.fx));
            if(vis[to.first*m+to.second][pd(1,A.fx)]==2e9) q.push((Q){A.sum+1,to.first,to.second,pd(1,A.fx)});
            to=G(A.x,A.y,pd(3,A.fx));
            if(vis[to.first*m+to.second][pd(3,A.fx)]==2e9) q.push((Q){A.sum+1,to.first,to.second,pd(3,A.fx)});
        }else{
            pair<int,int> to=G(A.x,A.y,pd(3,A.fx));
            if(vis[to.first*m+to.second][pd(3,A.fx)]==2e9) q.push((Q){A.sum,to.first,to.second,pd(3,A.fx)});
            to=G(A.x,A.y,pd(1,A.fx));
            if(vis[to.first*m+to.second][pd(1,A.fx)]==2e9) q.push((Q){A.sum+1,to.first,to.second,pd(1,A.fx)});
            to=G(A.x,A.y,pd(2,A.fx));
            if(vis[to.first*m+to.second][pd(2,A.fx)]==2e9) q.push((Q){A.sum+1,to.first,to.second,pd(2,A.fx)});
        }
    }
}




signed main()
{
    read(jk);while(jk--){
        read(n),read(m);
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                char ch=getchar();
                while(ch!='A'&&ch!='B'&&ch!='C') ch=getchar();
                a[i*m+j]=ch;
            }
        }
        for(int i=0;i<=n*m+m;i++) vis[i][1]=vis[i][2]=vis[i][3]=vis[i][4]=0;
        vis[n*m+m+1][1]=2e9;
        for(int i=m+1;i<=n*m+m;i++) vis[i][1]=vis[i][2]=vis[i][3]=vis[i][4]=2e9;
        ans=2e9;bfs();wh(ans);
    }
    return 0;
}
posted @ 2025-11-14 12:47  Red_river_hzh  阅读(39)  评论(0)    收藏  举报