bfs

ABC 235 D - Multiply and Rotate

题目链接
https://atcoder.jp/contests/abc235/tasks/abc235_d

解析

  • 注意bfs是一种工具,不局限于图论,本质是搜索
  • 本题相当于给出了两种扩展队列的规则,按照规则进行扩展求最短路即可
  • 感觉to_string()方法用于求数字的位数很nice

Ac代码

点击查看代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>

using namespace std;

typedef long long ll;

const int N = 1e7 + 10;

bool st[N];
int a, n;
int dist[N];

int qmi(int a, int k)
{
    int res = 1;
    while(k)
    {
        if(k & 1) res = (ll) res * a;
        k >>= 1;
        a = (ll)a * a;
    }
    return res;
}

int check1(int x){
    if(x < 10 || x % 10 == 0) return x;
    string s = to_string(x);
    int len = s.size();
    return x % 10 * qmi(10, len - 1) + x / 10;
}

int check2(int x){
    return a * x;
}

int main()
{
    scanf("%d%d", &a, &n);
    memset(dist, 0x3f, sizeof dist);
    string nn = to_string(n);
    int LEN = nn.size();

    queue<int> q;
    q.push(1);
    st[1] = true; dist[1] = 0;
    while(q.size()){
        auto t = q.front();
        q.pop();

        int newt = check1(t);
        string tt = to_string(newt);
        int lent = tt.size();
        if(lent <= LEN && !st[newt]){
            q.push(newt);
            st[newt] = true;
            dist[newt] = dist[t] + 1;
        }

        newt = check2(t);
        tt = to_string(newt);
        lent = tt.size();
        if(lent <= LEN && !st[newt]){
            q.push(newt);
            st[newt] = true;
            dist[newt] = dist[t] + 1;
        }
    }
    if(dist[n] == 0x3f3f3f3f) puts("-1");
    else printf("%d\n", dist[n]);

    return 0;
}

1855. 愤怒的奶牛

题目链接
https://www.acwing.com/problem/content/1857/

解析

一个一维的bfs+暴力,暴力枚举每一个最开始击中的点,然后通过bfs把所有符合要求的点加进队列,然后更新下一轮的点。需要注意的有两点:

  • 统计会爆炸的点的个数:将每个会爆炸的点加进队列,在每个点出队列的时候记一个cnt就行;不要只加入每轮引爆最左边和最右边的点,这样可能是不全面的。

  • 学习怎么一轮一轮地改变爆炸范围

Ac代码

点击查看代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <map>

using namespace std;

const int N = 110;

int cnt;
int start, n;
queue<int> q;
int a[N];
bool st[N];
map<int, int> mp;

void bfs(int x)
{
    cnt = 0;
    memset(st, 0, sizeof st);
    mp[x] = 1;
    q.push(x);
    st[x] = true;

    int right, left;
    while(q.size())
    {
        int s = q.front(); q.pop();
        cnt ++;
        left = s - 1, right = s + 1;

        while(left >= 1 && a[s] - a[left] <= mp[s]) {
            if(st[left]) left --;
            else{
                q.push(left);
                st[left] = true;
                mp[left] = mp[s] + 1;
                left --;
            }
        }

        while(right <= n && a[right] - a[s] <= mp[s]) {
            if(st[right]) right ++;
            else{
                q.push(right);
                st[right] = true;
                mp[right] = mp[s] + 1;
                right ++;
            }
        }
    }
    return;
}

int main()
{
    scanf("%d", &n);
    for(int i = 1; i <= n; i ++) scanf("%d", &a[i]);
    sort(a + 1, a + n + 1);

    int ans = 0;
    for(int i = 1; i <= n; i ++){
        bfs(i);
        ans = max(ans, cnt);
    }
    printf("%d\n", ans);

    return 0;
}

844. 走迷宫

题目链接
https://www.acwing.com/problem/content/846/

解析
bfs模板题

Ac代码

点击查看代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>

using namespace std;

typedef pair<int, int> PII;

const int N = 110;

int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};

int a[N][N], d[N][N];
bool st[N][N];
int n, m;
queue<PII> q;

void bfs(int xx, int yy)
{
    q.push({xx, yy});
    st[xx][yy] = true;
    d[1][1] = 0;
    
    while(q.size()){
        auto t = q.front(); q.pop();
        int tx = t.first, ty = t.second;
        
        for(int i = 0; i < 4; i ++){
            int x = tx + dx[i], y = ty + dy[i];
            if(x < 1 || x > n || y < 1 || y > m) continue;
            if(a[x][y] == 1) continue;
            if(st[x][y]) continue;
            if(d[x][y] > d[tx][ty] + 1){
                q.push({x, y});
                st[x][y] = true;
                d[x][y] = d[tx][ty] + 1;
            }
        }
    }
    return;
}

int main()
{
    scanf("%d%d", &n, &m);
    
    for(int i = 1; i <= n; i ++){
        for(int j = 1; j <= m; j ++){
            scanf("%d", &a[i][j]);
        }
    }
    
    memset(d, 0x3f, sizeof d);
    bfs(1, 1);
    
    printf("%d\n", d[n][m]);
    
    return 0;
}

845. 八数码

题目链接
https://www.acwing.com/problem/content/847/

解析
感觉像是一个状态压缩的bfs,需要注意的技巧有以下几点:

  • 字符串和3x3方格坐标的转化
  • <unordered_map> 有 .count()方法,可以发挥st数组的作用
  • 总是写错数组的边界,关于数组越界的判断要特别注意
  • swap很好用,string里交换字符也可以用swap

Ac代码

点击查看代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <map>

using namespace std;

const int N = 15;

string str = "12345678x";
string a;
queue<string> q;
unordered_map<string, int> d;

int find(string s, char x){
    for(int i = 0; i < 9; i ++)
        if(s[i] == x) return i;
    return -1;
}

int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};

int bfs(string a)
{
    q.push(a);
    d[a] = 0;
    
    while(q.size())
    {
        auto t = q.front(); q.pop();
        int distance = d[t];
        
        if(t == str) return d[t];
        
        int pos = find(t, 'x');
        int tx = pos / 3, ty = pos % 3;
        
        for(int i = 0; i < 4; i ++){
            int x = tx + dx[i], y = ty + dy[i];
            if(x < 0 || x >= 3 || y < 0 || y >= 3) continue;
            swap(t[pos], t[3 * x + y]);
            if(!d.count(t)){
                q.push(t);
                d[t] = distance + 1;
            }
            swap(t[pos], t[3 * x + y]);
        }
    }
    return -1;
}

int main()
{
    for(int i = 0; i < 9; i ++){
        char x;
        cin >> x;
        a += x;
    };
    
    printf("%d\n", bfs(a));
    
    return 0;
}

1471. 牛奶工厂

题目链接
https://www.acwing.com/problem/content/1473/

解析
暴力。和拓扑排序的板子有点像。

Ac代码

点击查看代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>

using namespace std;

const int N = 110;

int n;
int h[N], e[N], ne[N], idx;
bool st[N];

void add(int a, int b){
    e[idx] = b, ne[idx] = h[a], h[a] = idx ++;
}

bool bfs(int x)
{
    int cnt = 0;
    memset(st, 0, sizeof st);
    queue<int> q;
    q.push(x);
    st[x] = true;
    
    while(q.size()){
        auto t = q.front(); q.pop();
        cnt ++;
        for(int i = h[t]; i != -1; i = ne[i]){
            int j = e[i];
            if(!st[j]){
                q.push(j);
                st[j] = true;
            }
        }
    }
    if(cnt == n) return true;
    return false;
}

int main()
{
    scanf("%d", &n);
    memset(h, -1, sizeof h);
    for(int i = 1; i < n; i ++){
        int a, b;
        scanf("%d%d", &a, &b);
        add(b, a);
    }
    
    for(int i = 1; i <= n; i ++){
        if(bfs(i)){
            printf("%d\n", i);
            return 0;
        }
    }
    printf("-1\n");
    
    return 0;
}
posted @   小菜珠的成长之路  阅读(73)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架
点击右上角即可分享
微信分享提示