2020.4.6大一练习:广度优先搜索-BFS

总结:
BFS主要用来解决求“次数”“最小次数”“个数”等问题
要素:结构体、队列 、方向与判定
求次数要记得在结构体中定义变量用来存储每一步对应的次数值。


洛谷P1032

这题字符串+BFS

#include <bits/stdc++.h>
using namespace std;
#define num 10

string a, b;
string ason[num], atr[num];
int n, ans;
struct node
{
    string str;
    int step;
};
queue<node> q;
map<string, int> vis; //标记

string splice(string &str, int i, int j)
{
    string back = "";
    if (i + ason[j].length() > str.length()) //确认拼接长度是否超出
        return back;
    for (int k = 0; k < ason[j].length(); k++) //确认是否符合对应规则子串
        if (str[i + k] != ason[j][k])
            return back;
    back = str.substr(0, i);                  //取规则子串前字符
    back += atr[j];                           //取按规则转换后的字符
    back += str.substr(i + ason[j].length()); //取规则子串后字符
    return back;
}

void bfs()
{
    node s;
    s.str = a;
    s.step = 0;
    q.push(s);
    while (!q.empty())
    {
        node t = q.front();
        q.pop();
        if (vis[t.str]) //剪枝
            continue;
        if (t.str == b) //转换完成
        {
            ans = t.step;
            break;
        }
        vis[t.str] = 1; //标记已使用
        string temp;
        for (int i = 0; i < t.str.length(); i++) //遍历 从每个字母开始
            for (int j = 0; j < n; j++)          //从每个字母开始遍历n种转换规则
            {
                temp = splice(t.str, i, j);
                if (temp != "")
                {
                    node t2;
                    t2.str = temp;
                    t2.step = t.step + 1;
                    q.push(t2);
                }
            }
    }
    if (ans > 10 || ans == 0)
        cout << "NO ANSWER!" << endl;
    else
        cout << ans << endl;
}

int main()
{
    cin >> a >> b;
    while (cin >> ason[n] >> atr[n])
        n++;
    bfs();
    //system("pause");
    return 0;
}


A.湖计数-搜索

(A\F\G\J题都差不多,BFS模板题)

#include <bits/stdc++.h>
using namespace std;
char str[101][101];
int n, m, ans;
struct node
{
    int x;
    int y;
};
queue<node> q;
int xx[8] = {1, -1, 0, 0, 1, -1, 1, -1};
int yy[8] = {0, 0, 1, -1, 1, -1, -1, 1};
void bfs(int x, int y)
{
    q.push({x, y});
    while (!q.empty())
    {
        node tmp;
        tmp = q.front();
        q.pop();
        str[x][y] = '.';
        for (int i = 0; i < 8; i++)
        {
            int tx = tmp.x + xx[i];
            int ty = tmp.y + yy[i];
            if (tx >= 1 && tx <= n && ty >= 1 && ty <= m && str[tx][ty] != '.')
            {
                q.push({tx, ty});
                str[tx][ty] = '.';
            }
        }
    }
}
int main()
{
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; i++)
        cin >> str[i] + 1;
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= m; j++)
        {
            if (str[i][j] == 'W')
            {
                bfs(i, j);
                ans++;
            }
        }
    printf("%d\n", ans);
    //system("pause");
    return 0;
}

B.01迷宫-搜索

这题正常做会TLE。
推知,如示例
01
10
此类连通区域,不管从哪一个位置开始数,答案都是一样的(4)
所以我们可以把各个块的答案记录下来

#include <bits/stdc++.h>
using namespace std;
int n, m, x, y;
int xx[4] = {1, -1, 0, 0};
int yy[4] = {0, 0, 1, -1};
char str[1001][1001];
bool vis[1001][1001];
int piece[1001][1001], cnt;//用于记录块的图,cnt为块的计数器
int ans[100005];//保存每个块的答案数
struct node
{
    int x, y;
};
queue<node> q;
void bfs(int x, int y)
{
    q.push({x, y});
    vis[x][y] = 1;
    piece[x][y] = cnt;//这个点在第cnt个块
    ans[piece[x][y]]++;//第cnt个块的答案数+1
    while (!q.empty())
    {
        node tmp;
        tmp = q.front();
        q.pop();
        for (int i = 0; i < 4; i++)
        {
            int tx = tmp.x + xx[i];
            int ty = tmp.y + yy[i];
            if (tx >= 1 && tx <= n && ty >= 1 && ty <= n && vis[tx][ty] == 0)
            {
                if (str[tmp.x][tmp.y] != str[tx][ty])
                {
                    q.push({tx, ty});
                    vis[tx][ty] = 1;
                    piece[tx][ty] = cnt;
                    ans[piece[tx][ty]]++;
                }
            }
        }
    }
    cnt++;//不要忘记!
}
int main()
{
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; i++)
        scanf("%s", str[i] + 1);
    while (m--)
    {
        scanf("%d%d", &x, &y);
        if (vis[x][y] == 0)//如果为0则说明这是一个“新块”,查一遍
            bfs(x, y);
        printf("%d\n", ans[piece[x][y]]);//点在哪一个块内就输出该块的答案
    }
    //system("pause");
    return 0;
}


C.营救-搜索

这题莫名其妙卡了我很久,一直wa,究其原因我发现了下面这个玄学问题
在这里插入图片描述
查看原文点此
ios+cin+printf混用可过;
ios+cin+scanf是会出问题的

#include <bits/stdc++.h>
using namespace std;
char str[1005][1005];
int n, ans;
int st1, st2, ed1, ed2;
struct node
{
    int x;
    int y;
    int step;//这题求最小步数,结构体内需要记录每一个位置的当前步数
};
queue<node> q;
int xx[4] = {1, -1, 0, 0};
int yy[4] = {0, 0, 1, -1};
int bfs(int st1, int st2, int ed1, int ed2)
{
    q.push({st1, st2, 0});
    str[st1][st2] = '1';
    while (!q.empty())
    {
        node tmp;
        tmp = q.front();
        q.pop();
        if (tmp.x == ed1 && tmp.y == ed2)
            return tmp.step;
        for (int i = 0; i < 4; i++)
        {
            int tx = tmp.x + xx[i];
            int ty = tmp.y + yy[i];
            if (tx >= 1 && tx <= n && ty >= 1 && ty <= n && str[tx][ty] == '0')
            {
                q.push({tx, ty, tmp.step + 1});
                str[tx][ty] = '1';
            }
        }
    }
}
int main()
{
    ios::sync_with_stdio(false);//用了ios输入全用cin!!!
    cin >> n;
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++)
            cin >> str[i][j];
    cin >> st1 >> st2 >> ed1 >> ed2;
    ans = bfs(st1, st2, ed1, ed2);
    cout << ans << endl;
    //system("pause");
    return 0;
}

D.面积(area)-搜索

思路:在整个图的外层加上一圈0,在从(0,0)开始BFS把所有的0变为1(这样外面的0全部成了1),再数一遍有多少个0就行了

#include <bits/stdc++.h>
using namespace std;
int xx[4] = {1, -1, 0, 0};
int yy[4] = {0, 0, 1, -1};
int str[15][15];
struct node
{
    int x, y;
};
queue<node> q;
void bfs(int x, int y)
{
    q.push({x, y});
    while (!q.empty())
    {
        node tmp;
        tmp = q.front();
        q.pop();
        for (int i = 0; i < 4; i++)
        {
            int tx = tmp.x + xx[i];
            int ty = tmp.y + yy[i];
            if (tx >= 0 && tx <= 11 && ty >= 1 && ty <= 11 && str[tx][ty] == 0)
            {
                q.push({tx, ty});
                str[tx][ty] = 1;
            }
        }
    }
}
int main()
{
    for (int i = 0; i < 12; i++)
    {
        str[0][i] = 0;
        str[11][i] = 0;
    }
    for (int i = 0; i < 12; i++)
    {
        str[i][0] = 0;
        str[i][11] = 0;
    }
    for (int i = 1; i <= 10; i++)
        for (int j = 1; j <= 10; j++)
            scanf("%d", &str[i][j]);
    bfs(0, 0);
    int ans = 0;
    for (int i = 1; i <= 10; i++)
        for (int j = 1; j <= 10; j++)
            if (str[i][j] == 0)
                ans++;
    printf("%d\n", ans);
    //system("pause");
    return 0;
}


E.奇怪的电梯-搜索

#include <bits/stdc++.h>
using namespace std;
int n, a, b, k[501], vis[501];
struct node
{
    int x, step;
};
queue<node> q;
int main()
{
    int ans = -1;
    cin >> n >> a >> b;
    for (int i = 1; i <= n; i++)
        cin >> k[i];
    q.push({a, 0});
    vis[a] = 1;
    while (!q.empty())
    {
        node tmp;
        tmp = q.front();
        q.pop();
        if (tmp.x == b)
        {
            ans = tmp.step;
            break;
        }
        int tx = tmp.x + k[tmp.x];//往上走的情况
        if (tx <= n && vis[tx] == 0)
        {
            q.push({tx, tmp.step + 1});
            vis[tx] = 1;
        }
        tx = tmp.x - k[tmp.x];//往下走的情况
        if (tx >= 1 && vis[tx] == 0)
        {
            q.push({tx, tmp.step + 1});
            vis[tx] = 1;
        }
    }
    printf("%d\n", ans);
    //system("pause");
    return 0;
}


F.猴群-搜索

#include <bits/stdc++.h>
using namespace std;
char str[101][101];
int n, m, ans;
struct node
{
    int x;
    int y;
};
queue<node> q;
int xx[4] = {1, -1, 0, 0};
int yy[4] = {0, 0, 1, -1};
void bfs(int x, int y)
{
    q.push({x, y});
    while (!q.empty())
    {
        node tmp;
        tmp = q.front();
        q.pop();
        str[x][y] = '0';
        for (int i = 0; i < 4; i++)
        {
            int tx = tmp.x + xx[i];
            int ty = tmp.y + yy[i];
            if (tx >= 1 && tx <= n && ty >= 1 && ty <= m && str[tx][ty] != '0')
            {
                q.push({tx, ty});
                str[tx][ty] = '0';
            }
        }
    }
}
int main()
{
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; i++)
        cin >> str[i] + 1;
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= m; j++)
        {
            if (str[i][j] != '0')
            {
                bfs(i, j);
                ans++;
            }
        }
    printf("%d\n", ans);
    //system("pause");
    return 0;
}

G.瓷砖-搜索

#include <bits/stdc++.h>
using namespace std;
char str[101][101];
int n, m, ans;
struct node
{
    int x;
    int y;
};
queue<node> q;
int xx[4] = {1, -1, 0, 0};
int yy[4] = {0, 0, 1, -1};
int bfs(int x, int y)
{
    int cnt = 0;
    q.push({x, y});
    while (!q.empty())
    {
        node tmp;
        tmp = q.front();
        q.pop();
        cnt++;
        str[x][y] = '#';
        for (int i = 0; i < 4; i++)
        {
            int tx = tmp.x + xx[i];
            int ty = tmp.y + yy[i];
            if (tx >= 1 && tx <= n && ty >= 1 && ty <= m && str[tx][ty] != '#')
            {
                q.push({tx, ty});
                str[tx][ty] = '#';
            }
        }
    }
    return cnt;
}
int main()
{
    scanf("%d%d", &m, &n);
    for (int i = 1; i <= n; i++)
        cin >> str[i] + 1;
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= m; j++)
        {
            if (str[i][j] == '@')
            {
                ans = bfs(i, j);
                break;
            }
        }
    printf("%d\n", ans);
    //system("pause");
    return 0;
}

H.林大超市买水果-搜索

这题参考某dalao的用DFS写了……

#include <bits/stdc++.h>
using namespace std;
int m, n, k, price[35], vis[35], f = 0;
typedef long long ll;
void dfs(int tm, int cnt)
{
    if (f || cnt > k || tm < 0)//找到了、种数超过了、钱不够了→返回上一层
        return;
    if (tm == 0)
    {
        if (cnt == k)
        {
            f = 1;//可以满足条件
            return;
        }
        return;
    }
    for (int i = 1; i <= n; i++)
    {
        if (!vis[i])
        {
            vis[i] = 1;//标记
            dfs(tm - price[i], cnt + 1);//进入下一层
            vis[i] = 0;//回溯
        }
    }
}
int main()
{
    scanf("%d%d%d", &m, &n, &k);
    ll sum = 0;
    for (int i = 1; i <= n; i++)
    {
        scanf("%d", &price[i]);
        sum += price[i];//记和
    }
    if (k > n || sum < m)//这两种情况直接特判不必搜索
        printf("No\n");
    else
    {
        dfs(m, 0);
        f == 1 ? printf("Yes\n") : printf("No\n");
    }
    //system("pause");
    return 0;
}


I.逃出迷宫-搜索

(还没写……)


J.最大黑色区域-搜索

#include <bits/stdc++.h>
using namespace std;
int str[101][101];
int n, m, ans;
struct node
{
    int x;
    int y;
};
queue<node> q;
int xx[4] = {1, -1, 0, 0};
int yy[4] = {0, 0, 1, -1};
int bfs(int x, int y)
{
    int cnt = 0;
    q.push({x, y});
    while (!q.empty())
    {
        node tmp;
        tmp = q.front();
        q.pop();
        cnt++;
        str[x][y] = 0;
        for (int i = 0; i < 4; i++)
        {
            int tx = tmp.x + xx[i];
            int ty = tmp.y + yy[i];
            if (tx >= 1 && tx <= n && ty >= 1 && ty <= m && str[tx][ty] == 1)
            {
                q.push({tx,ty});
                str[tx][ty] = 0;
            }
        }
    }
    return cnt;
}
int main()
{
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= m; j++)
            scanf("%d", &str[i][j]);
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= m; j++)
        {
            if (str[i][j] == 1)
            {
                int cnt = bfs(i, j);
                ans = max(ans, cnt);
            }
        }
    printf("%d\n", ans);
    //system("pause");
    return 0;
}

BFS保存最短路路径并输出

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
(上图是模拟队列BFS)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值