1 专题说明
本专题用来记录使用DFS连通性模型或DFS搜索顺序求解的题目。
2 训练
题目1:1112迷宫
考点:dfs
C++代码如下,
#include <iostream>
#include <cstring>
using namespace std;
//宏定义
#define x first
#define y second
const int N = 110;
int n;
char g[N][N];
bool st[N][N];
pair<int,int> start_node, end_node;
int dirs[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
void dfs(int x, int y) {
st[x][y] = true;
//(x,y)可以走到哪里
for (int k = 0; k < 4; ++k) {
int nx = x + dirs[k][0];
int ny = y + dirs[k][1];
if (nx < 0 || nx >= n || ny < 0 || ny >= n) continue;
if (st[nx][ny]) continue;
if (g[nx][ny] == '#') continue;
dfs(nx, ny);
}
return;
}
int main() {
int T;
cin >> T;
while (T--) {
cin >> n;
for (int i = 0; i < n; ++i) cin >> g[i];
cin >> start_node.x >> start_node.y >> end_node.x >> end_node.y;
memset(st, 0, sizeof st); //每次都要进行重置
if (g[start_node.x][start_node.y] == '.' && g[end_node.x][end_node.y] == '.') {
dfs(start_node.x, start_node.y);
}
if (st[end_node.x][end_node.y]) {
cout << "YES" << endl;
} else {
cout << "NO" << endl;
}
}
return 0;
}
题目2:1113红与黑
C++代码如下,
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 30;
int n, m;
char g[N][N];
bool st[N][N];
int res = 0;
int dirs[4][2] = {{-1,0}, {1,0}, {0,-1}, {0,1}};
void dfs(int i, int j) {
for (int k = 0; k < 4; ++k) {
int x = i + dirs[k][0];
int y = j + dirs[k][1];
if (x < 1 || x > n || y < 1 || y > m) continue;
if (g[x][y] != '.') continue;
if (st[x][y]) continue;
st[x][y] = true;
res += 1;
dfs(x, y); //调用时判断,是否走过了
}
return;
}
int main() {
while (cin >> m >> n) {
if (m == 0 && n == 0) break;
memset(g, 0, sizeof g);
memset(st, 0, sizeof st);
res = 0;
for (int i = 1; i <= n; ++i) {
cin >> g[i] + 1;
}
pair<int, int> node_start;
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
if (g[i][j] == '@') {
node_start = make_pair(i, j);
}
}
}
res += 1;
dfs(node_start.first, node_start.second);
cout << res << endl;
}
return 0;
}
题目3:1116马走日
C++代码如下,
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 15;
int n, m;
bool visited[N][N];
int res = 0;
int dirs[8][2] = {{1,2}, {2,1}, {-1,2}, {-2,1}, {-1,-2}, {-2,-1}, {1,-2}, {2,-1}};
bool check() {
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
if (visited[i][j] == false) {
return false;
}
}
}
return true;
}
void dfs(int i, int j) {
if (check()) {
res += 1;
return;
}
for (int k = 0; k < 8; ++k) {
int x = i + dirs[k][0];
int y = j + dirs[k][1];
if (x < 0 || x >= n || y < 0 || y >= m) continue;
if (visited[x][y]) continue;
visited[x][y] = true;
dfs(x, y);
visited[x][y] = false;
}
return;
}
int main() {
int T;
cin >> T;
while (T--) {
int i, j;
cin >> n >> m >> i >> j;
//重置visited数组
memset(visited, 0, sizeof visited);
res = 0;
visited[i][j] = true;
dfs(i, j);
cout << res << endl;
}
return 0;
}
题目4:1117单词接龙
C++代码如下,
#include <iostream>
#include <cstring>
#include <algorithm>
#include <string>
#include <vector>
using namespace std;
int n;
vector<string> words;
vector<int> cnt;
string start_s;
int res = 1;
void dfs(string s) {
res = max(res, (int)s.size() - 1);
for (int j = s.size() - 1; j >= 1; --j) {
string t = s.substr(j);
//有多少word能接在t后面
for (int i = 0; i < words.size(); ++i) {
int idx = words[i].find(t);
if (idx == 0) {
//重合部分的长度为s.size() - j
if (t.size() == words[i].size()) continue; //跳过,检查下一个word
if (cnt[i] == 2) continue; //第i个单词已经用了2次了
int length = s.size();
s = s + words[i].substr(t.size());
cnt[i] += 1;
dfs(s);
cnt[i] -= 1;
s = s.substr(0, length);
}
}
}
return;
}
int main() {
cin >> n;
words.resize(n);
cnt.resize(n, 0); //每个单词至多被使用2次
for (int i = 0; i < n; ++i) cin >> words[i];
cin >> start_s;
string s = "_" + start_s;
dfs(s);
cout << res << endl;
return 0;
}
题目5:1118分成互质组
C++代码如下,
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int n;
vector<int> nums(15);
vector<vector<int>> group(15);
int groupsize = 0;
int res = 10;
int gcd(int x, int y) {
return y ? gcd(y, x % y) : x;
}
void dfs(int i, int groupsize) {
if (i == n) {
res = min(res, groupsize);
return;
}
int x = nums[i];
for (int j = 0; j < groupsize; ++j) {
//x能否放入第j组中
vector<int> a = group[j];
bool flag = true;
for (auto y : group[j]) {
if (gcd(x, y) != 1) {
flag = false;
break;
}
}
if (flag) {
group[j].emplace_back(x);
dfs(i + 1, groupsize);
group[j].pop_back();
}
}
group[groupsize].emplace_back(x);
dfs(i + 1, groupsize + 1);
group[groupsize].pop_back();
return;
}
int main() {
cin >> n;
for (int i = 0; i < n; ++i) cin >> nums[i];
dfs(0, 0);
cout << res << endl;
return 0;
}