Atcoder-ABC-431-E
网格图转向最短路问题
题目描述
给定一个 \(n \times m\) 的网格,每个格子标记为 A、B 或 C 类型。从起点 \((1, 1)\) 出发,初始方向向右,目标到达 \((n, m+1)\)(网格右侧外一格)且方向向右。
在不同的格子类型中转向有不同的代价规则:
- A 格:直行不消耗代价,左右转消耗 1
- B 格:左转不消耗代价,直行和右转消耗 1
- C 格:右转不消耗代价,直行和左转消耗 1
求从起点到终点的最小总代价。
输入格式
多组测试数据,每组包含:
- 网格大小 \(n, m\)
- \(n \times m\) 的网格,每个格子为
A、B或C
输出格式
每组数据输出一个整数,表示最小代价。
算法思路
状态设计
使用三元组 \((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;
}
本文来自博客园,作者:Red_river_hzh,转载请注明原文链接:https://www.cnblogs.com/Red-river-hzh/p/19203972

ABC-431-E
浙公网安备 33010602011771号