贴个F的代码
先考虑单纯的最短路,然后考虑限制一个方向且最多可到达一个障碍,求最小值。
#include <bits/stdc++.h>
int main(void) {
int n, m;
std::cin >> n >> m;
bool grid[n][m];
memset(grid, 0, sizeof(grid));
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
char ch;
std::cin >> ch;
grid[i][j] = (ch == '.');
}
}
constexpr int INF = 0x3f3f3f3f;
constexpr int offset[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
int ret1 = [&]() {
int dis[n][m];
memset(dis, 0x3f, sizeof(dis));
using T = std::tuple<int, int, int>; // dis, x, y
std::priority_queue<T, std::vector<T>, std::greater<>> heap;
heap.emplace(0, 0, 0);
while (!heap.empty()) {
auto [d, x, y] = heap.top();
heap.pop();
if (dis[x][y] <= d) {
continue;
}
if (x + 1 == n && y + 1 == m) {
return d;
}
dis[x][y] = d;
for (int i = 0; i < 4; ++i) {
int xx = x + offset[i][0], yy = y + offset[i][1];
if (xx >= 0 && xx < n && yy >= 0 && yy < m && grid[xx][yy] && d + 1 < dis[xx][yy]) {
heap.emplace(d + 1, xx, yy);
}
}
}
return INF;
}();
int ret2 = [&]() {
using ARRAY = std::array<int, 8>;
int dis[n][m][4][2];
memset(dis, 0x3f, sizeof(dis));
using T = std::tuple<int, int, int, int, int>; // dis, x, y, disacrd, selected
std::priority_queue<T, std::vector<T>, std::greater<>> heap;
for (int i = 0; i < 4; ++i) {
heap.emplace(0, 0, 0, i, 0);
}
while (!heap.empty()) {
auto [d, x, y, pos, state] = heap.top();
heap.pop();
if (dis[x][y][pos][state] <= d || dis[x][y][pos][state] <= d) {
continue;
}
if (x + 1 == n && y + 1 == m) {
return d;
}
dis[x][y][pos][state] = d;
for (int i = 0; i < 4; ++i) {
if (i == pos) {
continue;
}
int xx = x + offset[i][0], yy = y + offset[i][1];
if (xx >= 0 && xx < n && yy >= 0 && yy < m) {
if (grid[xx][yy]) {
if (d + 1 < dis[xx][yy][pos][state]) {
heap.emplace(d + 1, xx, yy, pos, state);
}
} else {
if (state == 0 && d + 1 < dis[xx][yy][pos][1]) {
heap.emplace(d + 1, xx, yy, pos, 1);
}
}
}
}
}
return INF;
}();
int ret = std::min(ret1, ret2);
if (ret == INF) {
ret = -1;
}
std::cout << ret << std::endl;
return 0;
}
查看11道真题和解析