#include <iostream>
using namespace std;
/*深度优先搜索 dfs算法
"一条路走到黑"
可以用递归实现
搜索树、迷宫
*/
/*实现迷宫
迷宫朴素解法:每一步尝试所有方向 dfs下一步+标记
//S入口 T出口 .可走 , *障碍
样例输入:
5 6
....S*
.***..
.*..*.
*.***.
.T....
输出:
....m*
.***mm
.*..*m
*.***m
.Tmmmm
9
测试最短更新
样例输入:
5 6
....S*
.**...
.*..*.
*..**.
.T....
输出:
...mm*
.**m..
.*mm*.
*mm**.
.T....
7
*/
#include<string>
int dir_01[4][2] = {{-1,0},{0,-1},{1,0},{0,1}}; //简化代码 四个方向,每行为 x,y 方向排序逆时针用得多 ,看题
int n_01,m_01;//行 列
string maze_01[110]; //一维存放地图 字符串数组
bool vis_01[110][110]; //地图路线标记
int ans_01 = 1000000000; //给大数,保证能更新答案
bool in_01(int x,int y) { //判断 x,y是否在取值范围内
return 0 <= x && x < n_01 && 0 <= y && y < m_01;
}
bool dfs_01(int x,int y,int step) { //输入下一步的坐标 判断是否可行 //step记录每种路径的长度,找到最短路径
if(maze_01[x][y] == 'T') {//到达终点
if(step < ans_01) { //更新
ans_01 = step;
}
return true;
}
vis_01[x][y] = 1; //标记1为走过
// if(maze_01[x][y] != 'S'){ } //第二次遍历 退回S时会改 ,或者
maze_01[x][y] = 'm';//标记S -- T 通路路径
for(int i = 0; i < 4; i++) {
int tx = x + dir_01[i][0];
int ty = y + dir_01[i][1];
//tx,ty不越界(取值范围内) 不是障碍物 且未走过 ,可以在此步(tx,ty)为基础搜索下一步
if(in_01(tx,ty) && maze_01[tx][ty] != '*' && !vis_01[tx][ty]) {
if(dfs_01(tx,ty,step + 1)) {
return true;
}
}
}
vis_01[x][y] = 0; //搜所有情况时(找最短)一定要恢复标记
maze_01[x][y] = '.';//恢复未走的状态
return false;
/*复杂版 copy也不慢
int tx = x - 1,ty = y ; //往左走 要遵循顺时针或逆时针方向判断!!!!!
if(in_01(tx,ty) && maze_01[tx][ty] != '*' && !vis_01[tx][ty]) { //不越界 且未走过 (走过还未到终点说明不通)
if(dfs_01(tx,ty)) {
return true;
}
}
tx = x ,ty = y - 1; //往下走
if(in_01(tx,ty) && maze_01[tx][ty] != '*' && !vis_01[tx][ty]) { //不越界 且未走过 (走过还未到终点说明不通)
if(dfs_01(tx,ty)) {
return true;
}
}
tx = x + 1,ty = y ; //往右走
if(in_01(tx,ty) && maze_01[tx][ty] != '*' && !vis_01[tx][ty]) { //不越界 且未走过 (走过还未到终点说明不通)
if(dfs_01(tx,ty)) {
return true;
}
}
tx = x ,ty = y + 1; //往上走
if(in_01(tx,ty) && maze_01[tx][ty] != '*' && !vis_01[tx][ty]) { //不越界 且未走过 (走过还未到终点说明不通)
if(dfs_01(tx,ty)) {
return true;
}
}
vis_01[x][y] = 0; //恢复标记 ,找全部解
maze_01[x][y] = '.';//恢复未走的状态
return false;
*/
}
void test_01() {
//输入迷宫地图
cin >> n_01 >> m_01;
for(int i = 0; i < n_01; i++) {
cin >> maze_01[i]; //每个位置存一行 m
}
int x, y,step;
for(int i = 0; i < n_01; i++) {
for(int j = 0; j < m_01; j++) {
if(maze_01[i][j] == 'S') {
x = i,y = j;//设立起始位置
}
}
}
if(dfs_01(x,y,0)) { //别忘了调用!
for(int i = 0; i < n_01; i++) { //有bug时先打印 测试
cout<< maze_01[i] << endl;
}
cout<< ans_01 <<endl; //输出最短路径长度 ans设置全局! ,此处没有把T终点变为m ,但是起点S 变成m,等效
} else {
cout<< "NO!" << endl;
}
return;
}
/*象棋走马
日字型
不超出棋盘 , 不走到有棋子处
S起点 T终点 #障碍 .通路
马走日字型能否 S --> T
样例输入:
.#....#S#
..#.#.#..
..##.#..#
......##.
...T.....
...#.#...
...#.....
...##....
.........
.##......
输出:
Yes
*/
#include<cstdio>
char s_02[10][10];
bool f_02;
int dir_02[8][2] = {{2,1},{1,2},{-1,2},{-2,1},{-2,-1},{-1,-2},{1,-2},{2,-1}}; //表示马能走的八个方向
bool vis_02[10][10];
bool in_02(int x,int y) { //判断 x,y是否在取值范围内
return 0 <= x && x < 10 && 0 <= y && y < 9;
}
void dfs_02(int x,int y) {
vis_02[x][y] = true; //访问时标记 true
//测试s_02[x][y] =='m'; 其他遍历完加return 且有做修改,不通均无return,最后要恢复 vis_02[x][y] = false; s_02[x][y] =='.';
if(f_02) {
return; //找到就结束 , 减少时间复杂度 !!
}
if(s_02[x][y] == 'T') { //找到出口
f_02 = true;
return;
}
for(int i = 0; i < 8; i++) { //遍历方向
int tx = x + dir_02[i][0];
int ty = y + dir_02[i][1];
if(in_02(tx,ty) && s_02[tx][ty] != '#' && !vis_02[tx][ty] ) { //不越界且未访问的情况下 判断下一步
dfs_02(tx,ty);
}
}
}
void test_02() {
int x,y;
for(int i = 0; i < 10; i++) {
scanf("%s",s_02[i]);
}
for(int i = 0; i < 10; i++) { //棋盘一半大小 10 * 9
for(int j = 0; j < 9; j++) {
if(s_02[i][j] == 'S') { //设立起始点
x = i;
y = j;
}
}
}
dfs_02(x,y);//别忘了!
/*测试
for(int i = 0; i < 10; i++) {
cout<<s_02[i] <<endl;
}
*/
if(f_02) {
printf("Yes\n");
} else {
printf("No\n");
}
}
/*搜索救援
.代表空地 , #代表草丛 ###连在一块的是一片草丛 ,所有格子之间都联通
每个草地需要派一个人去寻找 ,同一块草地的两个人可以相互看见,空地的人看不见草丛的人。
算出至少需要多少人救援 (求有几片草丛)
输入n m 行,列 ∈[1,100]
输入地图
样例输入:
5 6
.#....
..#...
..#..#
...##.
.#....
输出:
5
*/
#include<cstdio>
char mp_03[105][105];
bool vis_03[105][105];
int n_03,m_03;
void dfs_03(int x,int y) {
if(x < 0 || x >= n_03 || y < 0 || y >= m_03 || vis_03[x][y] || mp_03[x][y]== '.') { //超出边界或走到空地,遇到同一块草丛就连续不退出
return;
}
vis_03[x][y] = true; //走过标记为true
dfs_03(x - 1,y);
dfs_03(x,y - 1);
dfs_03(x + 1,y);
dfs_03(x,y + 1);
}
void test_03() {
int cnt = 0;
scanf("%d%d",&n_03,&m_03);
for(int i = 0; i < n_03; i++) {
scanf("%s",mp_03[i]);
}
for(int i = 0; i < n_03; i++) {
for(int j = 0; j < m_03; j++) {
if(!vis_03[i][j] && mp_03[i][j] == '#') {
dfs_03(i,j);
cnt++;
}
}
}
printf("%d\n",cnt);
return;
}
/*
样例输入:
5 5
s####
.####
.####
.####
....e
输出:
1
*/
int n_04,m_04,x_04,y_04,ans_04; //x,y表示行列下标
char mp_04[15][15];
bool vis_04[15][15];
void dfs_04(int x,int y) { //参数x != x_04 调试半天...
//此步坐标 超出边界或已经走过 或是障碍物 返回
if(x < 0 || x >= n_04 || y < 0 || y >= m_04 || vis_04[x][y] || mp_04[x][y]== '#') {
return;
}
if(mp_04[x][y] == 'e') { //到达终点
ans_04++; //统计通路数量
return;
}
vis_04[x][y] = true; //走过标记为true
//mp_04[x][y]= 'm';
dfs_04(x - 1,y);
dfs_04(x + 1,y);
dfs_04(x,y - 1);
dfs_04(x,y + 1);
vis_04[x][y] = false; //找所有路径 ,一定要情空标记
}
void test_04() {
scanf("%d%d",&n_04,&m_04);
for(int i = 0; i < n_04; i++) {
scanf("%s",mp_04[i]);//输入地图 一行占一位
}
for(int i = 0; i < n_04; i++) {
for(int j = 0; j < m_04; j++) {
if(mp_04[i][j] == 's') { //设置起点
x_04 = i;
y_04 = j;
}
}
}
dfs_04(x_04,y_04);
/*测试 地图 可标记走过处 元素m
for(int i = 0; i < n_04; i++) {
printf("%s\n",mp_04[i]);
}
*/
printf("%d\n",ans_04);
return;
}
/*求最大连续草丛(其余与test_03一致)
样例输入:
5 6
.#....
..#...
..#..#
...##.
.#....
输出:
2
*/
int n_05,m_05,cnt_05,ans_05;
char mp_05[1005][1005];
bool vis_05[1005][1005];
void dfs_05(int x,int y) {
//此步坐标 超出边界或已经走过 或不是草丛 返回
if(x < 0 || x >= n_05 || y < 0 || y >= m_05 || vis_05[x][y] || mp_05[x][y]== '.') {
return;
}
vis[x][y] = true; //走过标记为true
cnt_05++; //记录草丛大小
dfs_05(x - 1,y);
dfs_05(x,y - 1);
dfs_05(x + 1,y);
dfs_05(x,y + 1); //遍历一遍即可 ,不用清空标记
}
void test_05() { //先写主 再 完成dfs_05
scanf("%d%d",&n_05,&m_05);
for(int i = 0; i < n_05; i++) {
scanf("%s",mp_05[i]);//输入地图 一行占一位
}
for(int i = 0; i < n_05; i++) {
for(int j = 0; j < m_05; j++) {
if( !vis_05[i][j] && mp_05[i][j] == '#') { //此步未访问过,且不是障碍物
cnt_05 = 0;
dfs_05(i,j); //搜索草丛
if(ans_05 < cnt_05) { //找最大,更新
ans_05 = cnt_05;
}
}
}
}
printf("%d\n",ans_05); //最大连续草丛
return;
}
int main() {
test_05();
return 0;
}
迷宫1 --test_01