和昨天的题目一样这里我们也可以使用bfs,

按照题目给出的逻辑,火焰和人的移动逻辑相同,换言之人之能至者,火之可至者也。

所以只需用bfs搜索联通块就行,如果所在的地点没有踩过并且是杂草,那么火就能烧到这,换言之ans++

我认为这种题目其实比较模板

1. 使用向量数组来限制搜索范围(在我的知识范围之内模拟移动搜索的题目都可以使用向量数组通过遍历实现搜索)

2.用queue来实现bfs

3.visit确保不重复访问

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

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

bool check(int x,int y)
{
    if(x>=0 && x<n && y>=0 && y<m) return true;
    else return false;
}

int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cin >> n >> m;
    vector<string> mp(n);
    int cx,cy,ans=0;
    for(int i = 0; i < n; i++)
    {
        string s;
        cin >> s;
        for(int j = 0; j < m; j++)
        {
            if(s[j]=='@') {cx = i;cy=j;}
        }
        mp[i]=s;
    }
    vector<vector<bool>> visited(n, vector<bool>(m, false));
    queue<pair<int,int>> q;
    q.push({cx,cy});
    visited[cx][cy] = true;

    while(!q.empty())
    {
        auto [x,y] = q.front();
        q.pop();

        for(int i = 0; i < 4; i++)
        {
            int nx = x+dx[i], ny= y+dy[i];
            if(check(nx,ny))
            {
                if(visited[nx][ny]==false && mp[nx][ny] != '#')
                {
                    q.push({nx,ny});
                    visited[nx][ny]=true;
                    if(mp[nx][ny]=='!') ans++;
                } 
                
            }
        }
    }
    cout << ans << endl;
}

如果题目变成了找最佳放火位置,题目会变得更加有意思,

读者简单的思考一下就会发现如果按照我们原本的思路搜索,不管是dfs和bfs最后一定会超时,因为我们要记录每个点对应的(高度),最后更新最大值并且输出

说高度,我们可以用mc里面岩浆的蔓延来表示,高处的岩浆向下蔓延直到最后遇到杂草,每一次移动都降低高度。

问题其实不是搜索方式而是我们的搜索量太大了,我们可以尝试反向bfs从杂草出发更新每一个点的数值,最后非杂草区块的值越小就越块在该点释放接纳能够烧到所有杂草。感兴趣的可以用代码实现一下。