0-1BFS(双端队列BFS)
OIWIKI上面的解释(感觉0-1 BFS就是权值为 0 / 1 的 Dijkstra)
只有两种花费,一种是0,就是说上下左右不用魔法的走(push_front),一种是1,使用魔法走 5 * 5 正方形任意位置(push_back)

#include<bits/stdc++.h>
using namespace std;
#define endl "\n"
typedef long long ll;
const int N = 1e3 + 5;
struct Node{
int x, y;
};
deque<Node>q;
int n, m, ex, ey, sx, sy, dist[N][N];
int dir[4][2]={1,0,0,1,-1,0,0,-1};
char a[N][N];
void bfs(){
q.push_back({sx, sy});
dist[sx][sy] = 0;
while(!q.empty()){
auto [x, y] = q.front();
q.pop_front();
int now = dist[x][y];
for(int i = 0 ; i < 4; i++){
int nx = x + dir[i][0];
int ny = y + dir[i][1];
if(nx >= 1 && nx <= n && ny >= 1 && ny <= m && a[nx][ny] != '#'){
if(now < dist[nx][ny]){
dist[nx][ny] = now;
q.push_front({nx, ny});
}
}
}
for(int i = -2; i <= 2; i++){
for(int j = -2; j <= 2; j++){
int nx = x + i;
int ny = y + j;
if(nx >= 1 && nx <= n && ny >= 1 && ny <= m && a[nx][ny] != '#'){
if(now + 1 < dist[nx][ny]){
dist[nx][ny] = now + 1;
q.push_back({nx, ny});
}
}
}
}
}
}
int main(){
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
cin >> n >> m >> sx >> sy >> ex >> ey;
for(int i = 1; i <= n; i++){
for(int j = 1; j <= m; j++){
cin >> a[i][j];
}
}
memset(dist, 127, sizeof(dist));
bfs();
if(dist[ex][ey] < 1 << 30)cout << dist[ex][ey];
else cout << -1;
return 0;
}
和上面一题可以说是一模一样的,对于摧毁操作,就是相当于可以走到 5 * 5 正方形区域除了四个顶点外的点

#include<bits/stdc++.h>
using namespace std;
#define endl "\n"
typedef long long ll;
const int N = 505;
struct Node{
int x, y;
};
int n, m, dist[N][N];
int dir[4][2] = {1, 0, 0, 1, -1, 0, 0, -1};
char a[N][N];
deque<Node>q;
void bfs(){
memset(dist, 127, sizeof(dist));
q.push_back({1, 1});
dist[1][1]=0;
while(!q.empty()){
auto [x, y] = q.front();
q.pop_front();
int now = dist[x][y];
for(int i = 0; i < 4; i++){
int nx = x + dir[i][0];
int ny = y + dir[i][1];
if(nx >= 1 && nx <= n && ny >= 1 && ny <= m && a[nx][ny] != '#'){
if(dist[nx][ny] > now){
dist[nx][ny] = now;
q.push_front({nx, ny});
}
}
}
for(int i = -2; i <= 2; i++){
for(int j = -2; j <= 2; j++){
if(abs(i) == 2 && abs(j) == 2)continue;
int nx = x + i;
int ny = y + j;
if(nx >= 1 && nx <= n && ny >= 1 && ny <= m){
if(dist[nx][ny] > now + 1){
dist[nx][ny] = now + 1;
q.push_back({nx, ny});
}
}
}
}
}
}
int main(){
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
cin >> n >> m;
for(int i = 1; i <= n; i++){
for(int j = 1; j <= m; j++){
cin >> a[i][j];
}
}
bfs();
cout << dist[n][m] << endl;
return 0;
}
思路:就是维护一个双端队列,把向上和向下走看成边权为0,把向左和向右走看成边权为1,其实就是一个01边权的最短路问题。如果边权为0的话,从队头插入,如果边权为1的话,从队尾插入。保证每次出队的都是最小的。
值得注意的一点是左右走其实是对 y 操作(列) ,而上下走应该是对 x (行)操作

#include<bits/stdc++.h>
using namespace std;
#define endl "\n"
typedef long long ll;
const int N = 2e3 + 5;
struct Node{
int x, y, cntl, cntr;
};
int n, m, sx, sy, l, r, ans, vis[N][N];
int dir[4][2] = {1,0,0,1,-1,0,0,-1};
char a[N][N];
deque<Node>q;
void bfs(){
q.push_back({sx, sy, l, r});
while(!q.empty()){
// cout << 1 << endl;
auto [x, y, cntl, cntr] = q.front();
q.pop_front();
if(vis[x][y] || cntl < 0 || cntr < 0)continue;
ans++;
vis[x][y] = 1;
for(int i = 0; i < 4; i++){
int nx = x + dir[i][0];
int ny = y + dir[i][1];
if(nx >= 1 && nx <= n && ny >= 1 && ny <= m && a[nx][ny] != '*' && !vis[nx][ny]){
if(i % 2 == 0){
q.push_front({nx, ny, cntl, cntr});
}else{
if(i == 1)q.push_back({nx, ny, cntl, cntr - 1});
else q.push_back({nx, ny, cntl - 1, cntr});
}
}
}
}
cout << ans << endl;
}
int main(){
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
cin >> n >> m >> sx >> sy >> l >> r;
for(int i = 1; i <= n; i++){
for(int j = 1; j <= m; j++){
cin >> a[i][j];
}
}
bfs();
return 0;
}
P4667 [BalticOI 2011 Day1] Switch the Lamp On
思路:因为(1,1)必为 ‘ \ ’ 否则电路不可能连通, 而(n,m)必为 ' \ ' 否则不可能到达终点,那么我们就可以重构一张图,由(1,1)出发找出一张图,如果要转90度,就记录当前边权为1,对于无解情况就是看由(1,1)点出发重构的1图点(n,m)是否为 ' \ ' ,如果合法就做一个 0 - 1 BFS ( 代码写的很长,但是思路简单 )

#include<bits/stdc++.h>
using namespace std;
#define endl "\n"
typedef long long ll;
const int N = 505;
struct Node{
int x, y;
};
int n, m, val[N][N], vis[N][N], dist[N][N];
int dir[4][2] = {1,0,0,1,-1,0,0,-1};
char a[N][N];
void bfs(){
queue<Node>q;
q.push({1, 1});
if(a[1][1] == '/')val[1][1] = 1, a[1][1] = '\\';
while(!q.empty()){
auto [x, y] = q.front();
q.pop();
if(vis[x][y])continue;
vis[x][y] = 1;
for(int i = 0; i < 4; i++){
int nx = x + dir[i][0];
int ny = y + dir[i][1];
if(nx >= 1 && nx <= n && ny >= 1 && ny <= m && !vis[nx][ny]){
if(a[x][y] == a[nx][ny]){
if(a[x][y] == '\\')a[nx][ny] = '/';
else a[nx][ny] = '\\';
val[nx][ny] = 1;
}
q.push({nx, ny});
}
}
int nx, ny;
if(a[x][y] == '/'){
nx = x + 1; ny = y - 1;
if(nx >= 1 && nx <= n && ny >= 1 && ny <= m && !vis[nx][ny]){
if(a[nx][ny] != a[x][y]){
a[nx][ny] = a[x][y];
val[nx][ny] = 1;
}
q.push({nx, ny});
}
nx = x - 1; ny = y + 1;
if(nx >= 1 && nx <= n && ny >= 1 && ny <= m && !vis[nx][ny]){
if(a[nx][ny] != a[x][y]){
a[nx][ny] = a[x][y];
val[nx][ny] = 1;
}
q.push({nx, ny});
}
}else{
nx = x + 1; ny = y + 1;
if(nx >= 1 && nx <= n && ny >= 1 && ny <= m && !vis[nx][ny]){
if(a[nx][ny] != a[x][y]){
a[nx][ny] = a[x][y];
val[nx][ny] = 1;
}
q.push({nx, ny});
}
nx = x - 1; ny = y - 1;
if(nx >= 1 && nx <= n && ny >= 1 && ny <= m && !vis[nx][ny]){
if(a[nx][ny] != a[x][y]){
a[nx][ny] = a[x][y];
val[nx][ny] = 1;
}
q.push({nx, ny});
}
}
}
}
void bfs2(){
deque<Node>q;
memset(dist, 127, sizeof(dist));
q.push_front({1, 1});
dist[1][1] = val[1][1];
while(!q.empty()){
auto [x, y] = q.front();
q.pop_front();
for(int i = 0; i < 4; i++){
int nx = x + dir[i][0];
int ny = y + dir[i][1];
if(nx >= 1 && nx <= n && ny >= 1 && ny <= m){
if(val[nx][ny]){
if(dist[nx][ny] > dist[x][y] + 1){
dist[nx][ny] = dist[x][y] + 1;
q.push_back({nx, ny});
}
}else{
if(dist[nx][ny] > dist[x][y]){
dist[nx][ny] = dist[x][y];
q.push_front({nx, ny});
}
}
}
}
int nx, ny;
if(a[x][y] == '/'){
nx = x + 1; ny = y - 1;
if(nx >= 1 && nx <= n && ny >= 1 && ny <= m){
if(val[nx][ny]){
if(dist[nx][ny] > dist[x][y] + 1){
dist[nx][ny] = dist[x][y] + 1;
q.push_back({nx, ny});
}
}else{
if(dist[nx][ny] > dist[x][y]){
dist[nx][ny] = dist[x][y];
q.push_front({nx, ny});
}
}
}
nx = x - 1; ny = y + 1;
if(nx >= 1 && nx <= n && ny >= 1 && ny <= m){
if(val[nx][ny]){
if(dist[nx][ny] > dist[x][y] + 1){
dist[nx][ny] = dist[x][y] + 1;
q.push_back({nx, ny});
}
}else{
if(dist[nx][ny] > dist[x][y]){
dist[nx][ny] = dist[x][y];
q.push_front({nx, ny});
}
}
}
}else{
nx = x + 1; ny = y + 1;
if(nx >= 1 && nx <= n && ny >= 1 && ny <= m){
if(val[nx][ny]){
if(dist[nx][ny] > dist[x][y] + 1){
dist[nx][ny] = dist[x][y] + 1;
q.push_back({nx, ny});
}
}else{
if(dist[nx][ny] > dist[x][y]){
dist[nx][ny] = dist[x][y];
q.push_front({nx, ny});
}
}
}
nx = x - 1; ny = y - 1;
if(nx >= 1 && nx <= n && ny >= 1 && ny <= m){
if(val[nx][ny]){
if(dist[nx][ny] > dist[x][y] + 1){
dist[nx][ny] = dist[x][y] + 1;
q.push_back({nx, ny});
}
}else{
if(dist[nx][ny] > dist[x][y]){
dist[nx][ny] = dist[x][y];
q.push_front({nx, ny});
}
}
}
}
}
cout << dist[n][m];
}
int main(){
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
cin >> n >> m;
for(int i = 1; i <= n; i++){
for(int j = 1; j <= m; j++){
cin >> a[i][j];
}
}
bfs();
if(a[n][m] != '\\')cout << "NO SOLUTION";
else bfs2();
return 0;
}
傻逼题卡vector,但是做法应该没问题,对于每个#点行和列之间连边,跑 0 - 1BFS , 队列中记录下当前方向

#include<bits/stdc++.h> using namespace std; #define endl "\n" typedef long long ll; const int N = 1e3 + 5; struct Node{ int x, y, dir; }; vector<int> hang[N], lie[N]; int n, m, dist[N][N], vis[N][N]; char a[N][N]; deque<Node>q; void bfs(){ memset(dist, 127, sizeof(dist)); //0 左右 ,1 上下 q.push_back({1, 0, 0}); dist[1][0] = 0; while(!q.empty()){ auto [x, y, dir] = q.front(); // cout << x << ' ' << y << ' ' << dir << ' ' << endl; q.pop_front(); if(vis[x][y])continue; vis[x][y] = 1; if(dir == 0){ for(auto nxt : hang[x]){ if(nxt == y || vis[x][nxt])continue; if(dist[x][nxt] > dist[x][y]){ dist[x][nxt] = dist[x][y]; q.push_front({x, nxt, dir}); // cout << x << ' ' << nxt << ' ' << x << ' '<< y << endl; } } for(auto nxt : lie[y]){ if(nxt == x|| vis[nxt][y])continue; if(dist[nxt][y] > dist[x][y] + 1){ dist[nxt][y] = dist[x][y] + 1; q.push_back({nxt, y, dir ^ 1}); } // cout << nxt << ' ' << y << ' ' << x << ' '<< y << endl; } }else{ for(auto nxt : hang[x]){ if(nxt == y || vis[x][nxt])continue; if(dist[x][nxt] > dist[x][y] + 1){ dist[x][nxt] = dist[x][y] + 1; q.push_back({x, nxt, dir ^ 1}); } // cout << x << ' ' << nxt << ' ' << x << ' '<< y << endl; } for(auto nxt : lie[y]){ if(nxt == x|| vis[nxt][y])continue; if(dist[nxt][y] > dist[x][y]){ dist[nxt][y] = dist[x][y]; q.push_front({nxt, y, dir}); } // cout << nxt << ' ' << y << ' ' << x << ' '<< y << endl; } } } if(dist[n][m + 1] < 1 << 30)cout << dist[n][m + 1]; else cout << -1; } int main(){ ios::sync_with_stdio(false),cin.tie(0),cout.tie(0); cin >> n >> m; int jud = 0; map<pair<int, int>, int> mp; for(int i = 1; i <= n; i++){ for(int j = 1; j <= m; j++){ cin >> a[i][j]; if(a[i][j] == '#'){ // now++; // mp[now] = {i, j}; hang[i].push_back(j); lie[j].push_back(i); mp[{i, j}] = 1; if(i == n && mp[{1, j}]) jud = 1; } } } // now++; // mp[now] = {n, m + 1}; hang[n].push_back(m + 1); lie[m + 1].push_back(n); if(!jud)bfs(); else cout << 2; return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具