题解:CF173B Chamber of Secrets
题目分析
题意
题干很丑陋
于是自己转换了一下问题:
可以考虑成倒着跑,从 \((1, 1)\) 出发,方向向右,抵达 \((n, m+1)\)。
每次遇到 # 可以以 \(1\) 的代价更换方向。其余情况均只能以原方向前进。
求最小代价。
分析
考虑分层图最短路。
-
每一层只能沿一个方向移动,边权为 \(0\)。
-
在
#处向别的层连边,边权为 \(1\),表示切换方向代价为 \(1\)。
貌似一般的最短路算法被卡了。
我们容易发现该图中边权为 \(0\) 或 \(1\),考虑使用一些奇怪的技巧。
使用 01 BFS。顺带省去了建边的步骤。
时间复杂度 \(O(n)\)。
Code
#include<bits/stdc++.h>
using namespace std;
#define maxn 1003
int dis[maxn][maxn][4];
string mp[maxn];
struct st
{
int x, y, d;
st(int X, int Y, int D):x(X), y(Y), d(D) {}
};
deque<st> q;
int dx[]={1, -1, 0, 0};
int dy[]={0, 0, 1, -1};
#define chk(i, j) ((i)&&(j)&&(i<=n)&&(j<=m))
#define mp(i, j) mp[i][j-1]
/*
^
1
<3 2>
0
v
*/
void bfs(int n, int m)
{
memset(dis, 0x3f, sizeof dis);
q.emplace_back(1, 1, 2);
dis[1][1][2]=0;
while(!q.empty())
{
auto [x, y, p]=q.front();
q.pop_front();
if(!(dis[x+dx[p]][y+dy[p]][p]<=dis[x][y][p]||!chk(x+dx[p], y+dy[p])))
{
dis[x+dx[p]][y+dy[p]][p]=dis[x][y][p];
q.emplace_front(x+dx[p], y+dy[p], p);
}
if(mp(x, y)=='#')
for(int i=0;i<=3;i++)
{
if(i==p) continue;
if(dis[x+dx[i]][y+dy[i]][i]<=dis[x][y][p]+1||!chk(x+dx[i], y+dy[i])) continue;
dis[x+dx[i]][y+dy[i]][i]=dis[x][y][p]+1;
q.emplace_back(x+dx[i], y+dy[i], i);
}
}
}
int main()
{
int n, m;
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>mp[i];
bfs(n, m+1);
cout<<(dis[n][m+1][2]==0x3f3f3f3f?-1:dis[n][m+1][2]);
}

浙公网安备 33010602011771号