由样例可以得知,我们需要统计的是“外岛个数”,对于内部岛屿我们并不需要统计,对于外岛的状态标记我们可以用bfs来进行标记,但是关键点就在于如何准确寻找到外岛边缘并进行标记,又由图可以得知,如果有外岛存在,那么海域将会分隔,也就是说内部的海域在8个方向上都没能访问到外部海域,这就是其中一个突破点,因此我们可以引入“外海”概念,我们可以对原图进行拓展,在其余空白区域都标记为‘0’,作为外海,图像如下:
对于外海,我们可以用bfs逐一标记,并且遇到陆地的时候,进行另一个bfs,把当前的外岛进行标记,因为外海无法访问被环形岛围住的内海,因此不必担心会访问到内岛,需要特别注意的是对于每个变量的初始化,因为这道题目是多次询问多次操作,上一次的图可能会影响到下一次的图,因此要注意初始化,而对于统计外岛的个数,我们可以用全局变量cent来统计进入统计陆地的bfs的次数来获取答案
代码如下:
#include<iostream>
#include<cstring>
#include<queue>
#include<algorithm>
#include<string>
#define x first
#define y second//方便表示
using namespace std;
typedef pair <int, int> PII;
queue<PII> q;//对于海洋的
queue<PII> q1;//对于陆地的
const int N = 55;
char g[N][N];//存储地图
int T;//询问次数
int n, m;
bool st_sea[N][N];//存储每一块海的访问状态,如果访问过,那就是1,反之为0
bool st_load[N][N];//存储每一块陆地的访问状态,如果访问过,那就是1,反之为0
int dx[] = { 0,0,1,-1,1,1,-1,-1 };
int dy[] = { 1,-1,0,0,1,-1,1,-1 };
int cent = 0;//cent用于计数,一共有多少次进行访问陆地
void bfs_load(int x1, int y1)
{
while (!q1.empty()) q1.pop();//先对队列进行清空
q1.push({ x1,y1 });
st_load[x1][y1] = 1;
cent++;//对cent进行计数
while (!q1.empty()) {
auto t = q1.front(); q1.pop();
for (int i = 0; i < 4; i++) {
int a = t.x + dx[i], b = t.y + dy[i];
if (a < 0 || a > m + 1 || b < 0 || b > n + 1) continue;//如果越界,那就跳过
if (st_load[a][b]) continue;//如果访问过,那就跳过
if (g[a][b] != '1') continue;//如果当前不是陆地,就跳过
st_load[a][b] = st_load[t.x][t.y];
q1.push({ a,b });
}
}
return;
}
void bfs_sea(int x1, int y1)
{
memset(st_load, false, sizeof(st_load));//初始化陆地状态
memset(st_sea, false, sizeof(st_sea));//初始化海洋状态
q.push({ x1,y1 });
st_sea[x1][y1] = 1;//初始化
while (!q.empty()) {
auto t = q.front(); q.pop();
for (int i = 0; i < 8; i++) {
int a = t.x + dx[i], b = t.y + dy[i];
if (a < 0 || a > m + 1 || b < 0 || b > n + 1) continue;//如果越界,那就跳过
if (st_sea[a][b]) continue;//如果访问过,那就跳过
if (g[a][b] == '1' && !st_load[a][b]) bfs_load(a, b);//如果当前是陆地,并且没有访问过,那就进入bfs来标记陆地
if (g[a][b] != '0') continue;//如果当前不是海洋,就跳过
st_sea[a][b] = st_sea[t.x][t.y];//对海洋进行标记
q.push({ a,b });
}
}
return;
}
int main(void)
{
cin >> T;
while (T--) {
memset(g, '0', sizeof(g));//初始化地图
while (!q.empty()) {
q.pop();
}//对q进行清空
cent = 0;//初始化cent
cin >> m >> n;
for (int i = 1; i <= m; i++) {
string line;
cin >> line;
for (int j = 0; j < n; j++) {//直接用cin读入char类型二维数组会受到换行符的影响,因此可以用string类型读入一行,再每个字符进行处理
g[i][j + 1] = line[j];
}
}
bfs_sea(0, 0);
cout << cent << endl;
}
return 0;
}
案例也是全部通过了
希望对你有所帮助