CF1063B Labyrinth
题目大意:
一个\(n\)行,\(m\)列的迷宫,\('.'\)表示空地, \('*'\)表示障碍,可以向上下左右移动,但是左右移动时会有步数限制,求所能到达的格子数。(原题链接:Labyrinth)
输入格式:
第一行:\(n\), \(m\),表示迷宫行数和列数
第二行:\(r\), \(c\), 表示起点
第三行:\(x\), \(y\), 表示向左向右移动的最大步数
输出格式:
一个数:所能到达的格子数\(res\)
样例:
输入 \(1.\)
4 5
3 2
1 2
.....
.*.
...
*...
输出 \(1.\)
10
思路:
CF重思维真不是瞎说的,这道题一看完全没有思路~~
去官网翻了一下原题题解大体是这样:由于这题有向左最大步数向右最大步数两个限制,因此有点麻烦,但是我们可以发现一个限制:
向左走的步数 - 向右走的步数 = 起点横坐标 - 终点横坐标
因此我们就可以把它转化为一个限制啦,因为可以根据这个式子就可以由向左走的步数同时表示向右走的步数。因此我们只需要求出向左走的\(01\)最短路即可(可以用\(spfa\)来解决)。
最后计算答案时满足 向左步数 <= 向左最大步数 && 向左步数 + 横坐标之差 <= 最大向右步数 就计入答案。
还有这个只求向左走的最短路也是刚学到dist[xx][yy] > dist[t.first][t.second] + (i == 3)
···
代码:
#include <iostream>
#include <queue>
#include <cstring>
using namespace std;
#define Inf 0x3f3f3f3f
typedef pair<int, int> PII;
const int N = 2010;
int n, m, r, c, x, y;
char mp[N][N];
bool vis[N][N];
int dist[N][N];
int res;
int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};
void bfs(int x, int y)
{
queue<PII> q;
memset(dist, 0x3f, sizeof dist);
q.push({x, y});
vis[x][y] = true;
dist[x][y] = 0;
while(q.size())
{
auto t = q.front();
q.pop();
vis[t.first][t.second] = false;
for(int i = 0; i < 4; i++)
{
int xx = t.first + dx[i], yy = t.second + dy[i];
if(mp[xx][yy] == '.' && dist[xx][yy] > dist[t.first][t.second] + (i == 3))
{
dist[xx][yy] = dist[t.first][t.second] + (i == 3);
if(!vis[xx][yy])
{
vis[xx][yy] = true;
q.push({xx, yy});
}
}
}
}
}
int main()
{
cin >> n >> m >> r >> c >> x >> y;
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= m; j++)
{
cin >> mp[i][j];
}
}
bfs(r, c);
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= m; j++)
{
if(mp[i][j] == '.' && dist[i][j] <= x && dist[i][j] + j - c <= y) res++;
}
}
cout << res << endl;
return 0;
}