玩家无法移动到的地方炸弹产生的火肯定也烧不到,而玩家可以移动到的地方可以通过在起始点处放炸弹用火烧到,因此以初始点进行一次bfs判断四联通区域内有多少个草即可。

#include<bits/stdc++.h>
using namespace std;
#define LL long long
const LL dx[4]={-1,0,0,1},dy[4]={0,-1,1,0};
const LL maxn=1100,M=998244353,inf=1LL<<62;
LL n,m,sx,sy,ans=0;char a[maxn][maxn]={};
bool v[maxn][maxn]={};
bool ok(LL x,LL y){return (1<=x&&x<=n&&1<=y&&y<=m);}
queue<pair<LL,LL> >q;
void bfs(LL X,LL Y){
	q.push(make_pair(X,Y));v[X][Y]=1;
	while(!q.empty()){
		LL x=q.front().first,y=q.front().second;q.pop();
		if(a[x][y]=='!')ans++;
		for(LL i=0;i<4;i++){
			LL xx=x+dx[i],yy=y+dy[i];
			if(!ok(xx,yy))continue;
			if(a[xx][yy]=='#')continue;
			if(v[xx][yy])continue;
			v[xx][yy]=1;
			q.push(make_pair(xx,yy));
		}
	}
}
int main(){	
	scanf("%lld%lld",&n,&m);
	for(LL i=1;i<=n;i++)scanf("%s",a[i]+1);
	for(LL i=1;i<=n;i++)for(LL j=1;j<=m;j++)if(a[i][j]=='@')sx=i,sy=j;
	bfs(sx,sy);
	printf("%lld",ans);
	return 0;
}