广度优先搜索(BFS)专题
1.直接gg染色法
代码:
#include <bits/stdc++.h>
using namespace std;
int a[105][105], ans;
void dfs(int nx, int ny) {
if (nx < 0 || ny < 0 || nx > 11 || ny > 11)
return;
if (a[nx][ny] == 1) {
return;
}
a[nx][ny] = 1;
dfs(nx + 1, ny);
dfs(nx, ny + 1);
dfs(nx - 1, ny);
dfs(nx, ny - 1);
}
int main() {
for (int i = 1; i <= 10; i++)
for (int j = 1; j <= 10; j++) scanf("%d", &a[i][j]);
dfs(0, 0);
for (int i = 1; i <= 10; i++)
for (int j = 1; j <= 10; j++)
if (a[i][j] == 0)
ans++;
printf("%d", ans);
return 0;
}
2.BFS板子
代码:
#include <bits/stdc++.h>
#define pa pair<int, pair<int, int> >
#define mp make_pair
using namespace std;
int n, a[1005][1005], sx, sy, fx, fy, ans = 1e9, vis[1005][1005];
queue<pa> q;
int dx[] = {
-1, 0, 1, 0 };
int dy[] = {
0, 1, 0, -1 };
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("\n");
for (int j = 1; j <= n; j++) {
char c;
scanf("%c", &c);
a[i][j] = c - '0';
}
}
scanf("%d%d%d%d", &sx, &sy, &fx, &fy);
q.push(mp(0, mp(sx, sy)));
int now = 0;
vis[sx][sy] = 1;
while (!q.empty()) {
int nx = q.front().second.first;
int ny = q.front().second.second;
int now = q.front().first;
q.pop();
if (nx == fx && ny == fy) {
ans = min(ans, now);
}
for (int i = 0; i < 4; i++) {
int gx = nx + dx[i];
int gy = ny + dy[i];
if (gx <= 0 || gy <= 0 || gx > n || gy > n)
continue;
if (vis[gx][gy])
continue;
if (a[gx][gy])
continue;
vis[gx][gy] = 1;
q.push(mp(now + 1, mp(gx, gy)));
}
}
printf("%d", ans);
return 0;
}
3.同样为BFS板子,但是要记录状态
代码:
#include <bits/stdc++.h>
#define pa pair<int, pair<int, pair<int, int> > >
#define mp make_pair
using namespace std;
int n, m, a[1005][1005], sx, sy, fx, fy, ans = 1e9, vis[1005][1005];
queue<pa> q;
int dx[] = {
-1, 0, 1, 0 };
int dy[] = {
0, 1, 0, -1 };
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]);
scanf("%d%d%d%d", &sx, &sy, &fx, &fy);
q.push(mp(0, mp(0, mp(sx, sy))));
int now = 0;
vis[sx][sy] = 1;
while (!q.empty()) {
int nx = q.front().second.second.first;
int ny = q.front().second.second.second;
int now = q.front().second.first;
int nt = q.front().first;
q.pop();
if (nx == fx && ny == fy) {
ans = min(ans, now);
}
// printf("%d %d %d %d\n",nx,ny,now,nt);
for (int i = 0; i < 4; i++) {
int gx = nx + dx[i];
int gy = ny + dy[i];
int flag = 0;
if (gx <= 0 || gy <= 0 || gx > n || gy > m)
continue;
if (vis[gx][gy])
continue;
if (a[gx][gy])
continue;
// if(nx!=sx&&ny!=sy)
if (nt ^ (i % 2))
flag = 1;
int ynt = nt;
nt = i % 2;
vis[gx][gy] = 1;
q.push(mp(nt, mp(now + flag, mp(gx, gy))));
nt = ynt;
}
}
q.push(mp(1, mp(0, mp(sx, sy))));
memset(vis, 0, sizeof(vis));
now = 0;
vis[sx][sy] = 1;
while (!q.empty()) {
int nx = q.front().second.second.first;
int ny = q.front().second.second.second;
int now = q.front().second.first;
int nt = q.front().first;
q.pop();
if (nx == fx && ny == fy) {
ans = min(ans, now);
}
// printf("%d %d %d %d\n",nx,ny,now,nt);
for (int i = 0; i < 4; i++) {
int gx = nx + dx[i];
int gy = ny + dy[i];
int flag = 0;
if (gx <= 0 || gy <= 0 || gx > n || gy > m)
continue;
if (vis[gx][gy])
continue;
if (a[gx][gy])
continue;
// if(nx!=sx&&ny!=sy)
if (nt ^ (i % 2))
flag = 1;
int ynt = nt;
nt = i % 2;
vis[gx][gy] = 1;
q.push(mp(nt, mp(now + flag, mp(gx, gy))));
nt = ynt;
}
}
printf("%d", ans);
return 0;
}
4.与第三题原理相同
代码:
#include <bits/stdc++.h>
#define ll long long
using namespace std;
int a[80][80], b[80][80];
int n, m, x1, y3, x2, y2, h, t;
int fx[5] = {
0, 1, 0, -1, 0 }, fy[5] = {
0, 0, 1, 0, -1 };
char x;
struct k {
int x, y, s;
} s[6400];
bool check(int x, int y) {
if (b[x][y] != 1 && x > 0 && x <= n && y > 0 && y <= m)
return true;
else
return false;
}
int main() {
scanf("%d%d", &m, &n);
char x = getchar();
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
char x = getchar();
if (x == 'X')
a[i + 1][j + 1] = 1;
else
a[i + 1][j + 1] = 0;
}
char x = getchar();
} //构建迷宫
n += 2;
m += 2;
cin >> y3 >> x1 >> y2 >> x2;
while (x1 != 0) {
x1++;
y3++;
x2++;
y2++;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++) b[i][j] = a[i][j]; //复制迷宫
b[x2][y2] = 0; //终点解封
s[1].x = x1;
s[1].y = y3;
s[1].s = 0;
h = 0;
t = 1;
int c = 0;
do {
h++;
for (int i = 1; i <= 4; i++) {
int j = 1;
while (check(s[h].x + fx[i] * j, s[h].y + fy[i] * j)) //向一个方向一直走
{
if (b[s[h].x + fx[i] * j][s[h].y + fy[i] * j] != 2) {
t++;
s[t].x = s[h].x + fx[i] * j;
s[t].y = s[h].y + fy[i] * j;
s[t].s = s[h].s + 1;
b[s[t].x][s[t].y] = 2; //没走过的存入队列
if (s[t].x == x2 && s[t].y == y2) {
cout << s[t].s << endl;
c = 1; //到达终点,输出线段数
break;
}
}
j++;
}
if (c == 1)
break;
}
if (c == 1)
break; //存在路径,退出广搜
} while (h < t);
if (h == t)
cout << 0 << endl; //不存在路径,输出 0
scanf("%d%d%d%d", &y3, &x1, &y2, &x2);
}
return 0;
}