深度优先搜索
POJ-1979 Red and Black
从字符为 ‘@’ 的格子开始向 ‘.’ 的格子搜索,输出与之连通的 ‘.’ 的格子有多少个,包括 ‘@’ 在内。
1、DFS 内直接计数,能进入这个 DFS 的均是合法位置
2、为已经访问过的格子做标记,将原来的 ‘.’ 可达变为 ‘#’ 不可达
3、朝四个方向分别进行判断,位置合法:不超出范围、字符为 ‘.’,则进入
#include <iostream>
using namespace std;
const int maxn = 25;
char maze[maxn][maxn];
int n, m, sx, sy, cnt;
int dx[4] = {1, 0, -1, 0};
int dy[4] = {0, 1, 0, -1};
void dfs(int x, int y) {
cnt++;
maze[x][y] = '#';
for (int i = 0; i < 4; ++i) {
int nx = x + dx[i];
int ny = y + dy[i];
if (nx >= 0 && nx < n && ny >= 0 && ny < m && maze[nx][ny] == '.')
dfs(nx, ny);
}
}
int main() {
ios::sync_with_stdio(false);
while (cin >> m >> n && n && m) {
cnt = 0;
for (int i = 0; i < n; ++i) for (int j = 0; j < m; ++j) {
cin >> maze[i][j];
if (maze[i][j] == '@') sx = i, sy = j;
}
dfs(sx, sy);
cout << cnt << endl;
}
return 0;
}
AOJ-0118 Property Distribution
统计有多少联通快,这里联通块指相邻的方格中的字符是相等的。注意,图中有多种字符连通块。
1、由于有多种字符,故相比于 POJ-1979,DFS 增加了一个 char
类型的参数,避免将字符写死
2、只要是没有被访问过的字符,且字符等于当前 DFS 访问的字符 (char
参数),即进入递归过程
#include <iostream>
using namespace std;
const int maxn = 100 + 5;
char maze[maxn][maxn];
int h, w;
const int dx[4] = {0, -1, 0, 1};
const int dy[4] = {1, 0, -1, 0};
void dfs(int x, int y, char c) {
maze[x][y] = 'V';
for (int i = 0; i < 4; ++i) {
int nx = x + dx[i];
int ny = y + dy[i];
if (nx >= 0 && nx < h && ny >= 0 && ny < w && c == maze[nx][ny])
dfs(nx, ny, c);
}
}
int main() {
ios::sync_with_stdio(false);
while (cin >> h >> w && h && w) {
int ans = 0;
for (int i = 0; i < h; ++i)
for (int j = 0; j < w; ++j)
cin >> maze[i][j];
for (int i = 0; i < h; ++i) {
for (int j = 0; j < w; ++j) {
if (maze[i][j] != 'V') {
dfs(i, j, maze[i][j]);
ans++;
}
}
}
cout << ans << endl;
}
return 0;
}
AOJ-0033 BALL
给定一个序列,长度为定长 10 10 ,问是否可以将此序列分为两个子序列,保证两个子序列均是递增的,子序列可以不连续。
1、子集枚举或者递归均可
2、子集枚举使用二进制判断,对从 1~1024 的每个整形表达的二进制形态判断,取 0 和 1 的两个子集是否有序
3、递归则分为两种情况,选取和不选取。在递归的结束分别判断选取和不取的情况是否符合要求
4、此问题类似于背包问题,背包问题是最优化问题,而此问题是存在问题。若要用动态规划解决此问题,首先应该将存在问题转化为最优化问题
// 子集枚举版
#include <bitset>
#include <iostream>
using namespace std;
int T;
const int maxn = 10;
int ball[maxn];
int main() {
ios::sync_with_stdio(false);
cin >> T; while (T--) {
for (int i = 0; i < maxn; ++i) cin >> ball[i];
bitset<10> bs;
int all = 1024;
while (all--) {
bs = static_cast<bitset<10>>(all);
bool perfect = true;
int left = 0, right = 0;
for (int i = 0; i < 10; ++i) {
if (bs[i]) {
if (ball[i] > left) left = ball[i];
else {
perfect = false; break;
}
}
else {
if (ball[i] > right) right = ball[i];
else {
perfect = false;
break;
}
}
}
if (perfect) break;
}
if (all >= 0) cout << "YES" << endl;
else cout << "NO" << endl;
}
return 0;
}
POJ-3009 Curling 2.0
广度优先搜索
AOJ-0558 Cheese
POJ-3669 Meteor Shower
参考了优快云-Keaper大佬的博客,他的代码简洁漂亮值得学习。
BFS 搜索,找到一个永远不会被破坏的格点,并求出到这个格点的最短距离。所谓破坏,即第 t
秒钟会在 x,y
处出现陨石,将这个点及其周围的四个点同时摧毁,被摧毁的格点不可再通过,但在被摧毁之前可以通过。
1、以 a[i][j]
记录 i, j
最早被摧毁的时刻,d[i][j]
记录最早可以到达 i, j
的时间
2、使用 BFS 拓展可到达的区域。若该区域早已经被损毁,则不再走此区域;若该区域未被摧毁,且未被访问(因为如果被访问过则一定比当前这次访问更早,再访问该点也就没有意义了),则加入队列访问
3、直到找到一个历史上和未来均不会被毁灭的格点,该格点即安全区域,停止搜索
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
const int MAX = 300 + 10;
const int INF = 0x3f3f3f3f;
int a[MAX][MAX], d[MAX][MAX];
int dx[4] = { 0, 1, 0, -1 };
int dy[4] = { 1, 0, -1, 0 };
typedef pair<int, int> P;
typedef long long ll;
int bfs() {
if (a[0][0] == 0) return -1;
memset(d, 0x3f, sizeof(d));
queue<P> que;
que.push(P(0, 0));
d[0][0] = 0;
while (!que.empty()) {
int x = que.front().first;
int y = que.front().second;
que.pop();
if (a[x][y] == INF) {
return d[x][y];
break;
}
for (int i = 0; i < 4; ++i) {
int nx = x + dx[i];
int ny = y + dy[i];
if (nx >= 0 && ny >= 0 && a[nx][ny] > d[x][y] + 1 && d[nx][ny] == INF) {
d[nx][ny] = d[x][y] + 1;
que.push(P(nx, ny));
}
}
}
if (que.empty()) return -1;
}
int main() {
int m;
while (scanf("%d", &m) != EOF) {
memset(a, 0x3f, sizeof(a));
for (int i = 0; i < m; ++i) {
int x, y, t;
scanf("%d%d%d", &x, &y, &t);
a[x][y] = min(a[x][y], t);
for (int j = 0; j < 4; ++j) {
int nx = x + dx[j];
int ny = y + dy[j];
if (nx >= 0 && ny >= 0) {
a[nx][ny] = min(a[nx][ny], t);
}
}
}
int ans = bfs();
printf("%d\n", ans);
}
return 0;
}