0-1BFS(双端队列BFS)

OIWIKI上面的解释(感觉0-1 BFS就是权值为 0 / 1 的 Dijkstra)

 


[ABC176D] Wizard in Maze

 

 

 只有两种花费,一种是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;
}
View Code

 


[ABC213E] Stronger Takahashi

 

 

和上面一题可以说是一模一样的,对于摧毁操作,就是相当于可以走到 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;
}
View Code

 


Labyrinth

 

 

思路:就是维护一个双端队列,把向上和向下走看成边权为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;
}
View Code

 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;
}
View Code

 

Chamber of Secrets

傻逼题卡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;
}
View Code

 

posted @ 2023-08-08 22:49  zhujio  阅读(67)  评论(0编辑  收藏  举报