几道比较不错的深搜练习题(迷宫、红与黑、马走日、单词接龙,纯暴力无优化无剪枝)
写出深搜很重要的两点:1递归搜索树 2明确当前的状态
来源:acwing
//剖析一下自己写的深搜代码
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 110;
int k, n;
int a, b, c, d;
char g[N][N];
int dx[] = {1, 0, -1, 0}, dy[] = {0, 1, 0, -1};
bool st[N][N];
bool dfs(int x, int y){ //我用的是带返回值的dfs函数,也可以用一个不带返回值的,但是需要用变量标记一下
if(x == c && y == d) return true; //终止条件
st[x][y] = true;
for(int i = 0;i < 4;i++){
int tx = x + dx[i], ty = y + dy[i];
if(tx < 1 || tx > n || ty < 1 || ty > n) continue;
if(st[tx][ty] || g[tx][ty] == '#') continue;
if(dfs(tx, ty)) return true; //从终止条件那里一直迭代回到根节点
}
return false; //这个false只有在第一层才会有效果
}
int main(){
cin >> k;
while(k--){
memset(st, false, sizeof st);
cin >> n;
for(int i = 1;i <= n;i++)
for(int j = 1;j <= n;j++)
cin >> g[i][j];
cin >> a >> b >> c >> d;
a ++ , b ++ , c ++ , d ++; //注意下标起始位置,习惯从1开始的要注意这道题给的起点
if(g[a][b] == '#'){ //小坑:起点处就是障碍物那么肯定到不了
cout << "NO" << endl;
continue;
}
cout << (dfs(a, b) ? "YES" : "NO") << endl;
}
return 0;
}

来源:acwing
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 25;
int n, m;
char g[N][N];
bool st[N][N];
int dx[] = {1, 0, -1, 0}, dy[] = {0, 1, 0, -1};
int dfs(int x, int y){ //应用带返回值的dfs
st[x][y] = true; //连通性问题无需回溯
int sum = 1; //当前这个结点默认有1个
for(int i = 0;i < 4;i++){
int tx = x + dx[i], ty = y + dy[i];
if(tx < 1 || tx > n || ty < 1 || ty > m) continue;
if(st[tx][ty] || g[tx][ty] == '#') continue;
sum += dfs(tx, ty); //把从这个点遍历的加回来,相当于动态规划的感觉
} //第一层返回的就是我们要的结点数
return sum;
}
int main(){
while(cin >> m >> n, n | m){
memset(st, false, sizeof st);
int x, y;
for(int i = 1;i <= n;i++)
for(int j = 1;j <= m;j++){
cin >> g[i][j];
if(g[i][j] == '@') x = i, y = j;
}
cout << dfs(x, y) << endl;
}
return 0;
}

来源acwing
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 13;
int t;
int n, m, x, y;
bool st[N][N];
int dx[] = {1, 2, 2, 1, -1, -2, -2, -1}, dy[] = {-2, -1, 1, 2, 2, 1, -1, -2};
int dfs(int x, int y, int s){ //加个参数方便判断是否走全
if(s == n * m) return 1;
int ans = 0; //记录一下
st[x][y] = true;
for(int i = 0;i < 8;i++){
int tx = x + dx[i], ty = y + dy[i];
if(tx < 1 || tx > n || ty < 1 || ty > m) continue;
if(st[tx][ty]) continue;
ans += dfs(tx, ty, s + 1);
}
st[x][y] = false; //需要回溯
return ans;
}
int main(){
cin >> t;
while(t--){
memset(st, false, sizeof st);
cin >> n >> m >> x >> y;
x ++ , y ++;
cout << dfs(x, y, 1) << endl;
}
return 0;
}

来源:acwing
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <unordered_map>
using namespace std;
const int N = 30;
int n, d, length, ans;
char c;
string str[N];
unordered_map<string, int> m;
int is_fixed(string s, string t){ //算最少重合数
int res = 0;
for(int i = 1;i < min((int)s.size(), (int)t.size());i++){
res = i;
for(int j = 0;j < i;j++)
if(s[s.size() - i + j] != t[j]){
res = 0;
break;
}
if(!res) continue;
else return res;
}
return res;
}
int dfs(string s){
ans = max(ans, (int)s.size());
string q = s;
for(int i = 0;i < n;i++){
if(m[str[i]] && (d = is_fixed(s, str[i]))){
s += str[i].substr(d, str[i].size() - d);
m[str[i]]--;
dfs(s);
s = q;
m[str[i]]++; //回溯
}
}
return ans;
}
int main(){
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0); //加速
cin >> n;
for(int i = 0;i < n;i++){
cin >> str[i];
m[str[i]] = 2;
}
cin >> c;
for(int i = 0;i < n;i++)
if(str[i][0] == c){
ans = 0;
m[str[i]]--;
length = max(length, dfs(str[i]));
}
cout << length << endl;
return 0;
}
6967

被折叠的 条评论
为什么被折叠?



