当操作对象是两个数的时候,优先考虑用其中一个数表示另一个数,减少变量个数,一般用到map存
涉及两个数的关系问题
flood fill && BFS
#include <iostream>
#include <algorithm>
#define x first
#define y second
using namespace std;
const int N = , M = N*N;
typedef pair<int,int> PII;
int n;
bool st[N][N];
char/int g[N][N];
PII q[M];
// 辐射式偏移
int dx[8] = {-1, -1, -1, 0, 1, 1, 1, 0};
int dy[8] = {-1, 0, 1, 1, 1, 0, -1, -1};
//上下左右偏移
int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};
//日字形偏移
int dx[8] = {-2, -1, 1, 2, 2, 1, -1, -2};
int dy[8] = {1, 2, 2, 1, -1, -2, -2, -1};
void bfs(int sx,int sy)
{
int hh = 0, tt = 0;
q[0] = {sx,sy};
st[sx][sy] = true;
while(hh <= tt)
{
auto t = q[hh ++];
for(int i = 0 ; i < 8 ; i ++)
{
int a = t.x + dx[i];
int b = t.y + dy[i];
if(a < 0 || a >= n || b < 0 || b >= m) continue;//边界判断
if(g[a][b] ... || st[a][b]) continue;//条件符合以及是否已经被遍历过的判断
st[a][b] = true;//防止重复遍历
q[++tt] = {a,b};//使得整个连通块全部被遍历完全
}
}
}
int main()
{
cin >> n >> m;
for(int i = 0 ; i < n ; i ++)
for(int j = 0 ; j < m ; j ++)
cin >> g[i][j];
int cnt = 0;
for(int i = 0 ; i < n ; i ++)
for(int j = 0 ; j < m ; j ++)
{
if(g[i][j] ... && !st[i][j])
{
bfs(i,j);
cnt ++;
}
}
cout << cnt << endl;
return 0;
}
DFS板子
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 110;
int n,m;
int x1,y1,x2,y2;
char g[N][N];
bool st[N][N];
int dx[4] = {0,1,0,-1} , dy[4] = {1,0,-1,0};
bool dfs(int x,int y)
{
if(x == x2 && y == y2) return true;
st[x][y] = true;//内部dfs不需要恢复现场
for (int i = 0; i < 4; i ++ )
{
int a = x + dx[i];
int b = y + dy[i];
if(a < 0 || a >= m || b < 0 || b >= m) continue;
if(g[a][b] == '#') continue;
if(st[a][b]) continue;
if(dfs(a,b)) return true;
}
return false;
}
//当是多次查询时,记得重新memset一遍st数组为假
//dfsFLOOD FILL
int dfs(int x,int y)
{
int num = 1;
st[x][y] = true;//内部dfs不需要恢复现场
for (int i = 0; i < 4; i ++ )
{
int a = x + dx[i];
int b = y + dy[i];
if(a < 0 || a >= n || b < 0 || b >= m) continue;
if(g[a][b] == '#') continue;
if(st[a][b]) continue;
num += dfs(a,b);
}
return num;
}