【深度优先算法】

【深度优先算法】

沿着某条路径遍历,直到末端,然后回溯,再遍历另一条路径(走没有走过的岔路口)做同样的遍历,直到所有的节点都被访问,即回溯到源节点并且源节点已无未被访问的子节点。

库克船长的宝藏

库克船长在无名岛上埋藏了一些宝藏,找到它们需要路过一片沼泽地,rain在库克船长的笔记里面发现了通过沼泽的方法,沼泽地里铺满了石头,都是库克船长早就铺好的,石头都是蓝色或者绿色,绿色的石头铺成的路是可以走的,蓝色的石头踩上会被沼泽吞没。rain一开始站在一块绿色的石头上,并且rain从一块石头可以向上下左右四个方向移动到其他的石头上,但是他不能移动到蓝色的石头上,只能移动到绿色石头上。请你编程计算rain可以走到的绿色石头最多有多少块。
数据范围与提示:
1≤W,H≤20
输入描述:
输入包含多组测试数据。
每组输入首先是两个正整数 W 和 H,分别表示石头的列行数。(1≤W,H≤20)
接下来 H 行,每行包含 W 个字符,字符含义如下:
‘.’表示绿石头;
‘#’表示蓝石头;
‘@’表示rain一开始站的位置,此位置是一块绿石头,并且这个字符在每组输入中仅会出现一个。
当 W=0,H=0 时,输入结束。
数据范围与提示:
1≤W,H≤20
输出描述:
对于每组输入,输出rain可以走到的绿色石头最多有多少块,包括rain最开始站的那块绿色石头。
用例输入:
6 9
…#.
…#





#@…#
.#…#.
11 9
.#…
.#.#######.
.#.#…#.
.#.#.###.#.
.#.#…@#.#.
.#.#####.#.
.#…#.
.#########.

11 6
…#…#…#…
…#…#…#…
…#…#…###
…#…#…#@.
…#…#…#…
…#…#…#…
7 7
…#.#…
…#.#…
###.###
…@…
###.###
…#.#…
…#.#…
0 0
用例输出:
45
59
6
13

#include <bits/stdc++.h>
using namespace std;
char mp[50][50];
int w,h,ans;
int g[4][2]={-1,0,1,0,0,-1,0,1};
void dfs(int x,int y){
	ans++;
	mp[x][y]='#';
	for(int i=0;i<4;i++){
		int nx=x+g[i][0];
		int ny=y+g[i][1];
		if(nx >= 1 && nx <=h && ny >= 1 && ny <=w && mp[nx][ny]!='#'){
			dfs(nx,ny);
		}
	}
}
int main(){
	while(12){
		int x,y;
		cin>>w>>h;
		if(w==0 && h==0){
			break;
		}
		for(int i=1;i<=h;i++){
			for(int j=1;j<=w;j++){
				cin>>mp[i][j];
				if(mp[i][j]=='@'){
					x=i;y=j;
				}
			}
		}
		ans=0;
		dfs(x,y);
		cout<<ans<<endl;
	}
	return 0;
}

探索迷宫

描述

有一个m*n格的迷宫(表示m行、n列),用0表示可以走,1表示不可以走,从迷宫的(1,1)位置开始出发,到指定的位置停止(两个数据描述,分别表示行和列)。走时只能是“上下左右”四个方向。如果无法到达输出”NO”(表示无路),否则输出”YES”。注:第一行第一列元素坐标为(1,1)。

输入描述

第一行是两个数m,n(1<n,m<20),接下来是m行n列由1和0组成的数据。最后一行表示终点的坐标。

输出描述

如果能到达输出YES,否则输出NO。

用例输入 1

5 6
0 0 0 1 0 1
1 1 1 1 0 0
0 0 0 1 1 0
0 0 0 0 0 1
0 0 1 0 1 0
3 3
用例输出 1

NO

#include <bits/stdc++.h>
using namespace std;
int mp[12][12],vis[12][12];
int n,flag=0,ex,ey,m;
int dx[4]={-1,0,1,0};
int dy[4]={0,1,0,-1};
void dfs(int x,int y){
    if(x==n && y==n){
        flag=1;
        return;
    }
    for(int i=0;i<4;i++){
        int xx=x+dx[i];
        int yy=y+dy[i];
        if(xx>0 && xx<=n && yy>0 && yy<=n ){
            if(mp[xx][yy]==0 && vis[xx][yy]==0){
                vis[xx][yy]=1;
                dfs(xx,yy);
            }
        }
    }
}
int main(){
	cin>>m>>n;
	for(int i=1;i<=m;i++){
		for(int j=1;j<=n;j++){
			cin>>mp[i][j];
		}
	}
	cin>>ex>>ey;
	
    if(mp[1][1]==1 || mp[ex][ey]==1){
		cout<<"NO"<<endl;
		return 0;
	}else{
		vis[1][1]=1;
		dfs(1,1);
	}
    if(flag==true) cout<<"YES";
    else cout<<"NO";
	return 0;
}

学习象棋

描述

Ann在学校报了象棋兴趣小组,从来不会下象棋的童童非常兴奋。
学会了下象棋,Ann总想也教会程程,以后可以一起玩,周末两个小伙伴一起玩。Ann告诉程程,象走田,马走日。但是程程总是掌握不好马是怎么移动的。于是Ann给他做了,马的专项练习,给程程马的初始位置,然后让程程计算不重复的走过棋盘所有的点,有多少条路径。棋盘大小是 n×m (n和m<10)的。
棋盘那么大,程程很迷茫,希望会编程的你,能用计算机帮助他。

输入描述

第一行为整数 T (T<10),表示测试数据组数。
每一组测试数据包含一行,为四个整数,分别为棋盘的大小以及初始位置坐标 n,m,x,y。(0≤x≤n-1,0≤y≤m-1, m<10, n<10)。

输出描述

每组测试数据包含一行,为一个整数,表示马能遍历棋盘的途径总数,0 为无法遍历一次。

用例输入 1

1
5 4 0 0
用例输出 1

32

#include <bits/stdc++.h>
using namespace std;
int vis[15][15];
int g[8][2]={-2,1,-1,2,1,2,2,1,2,-1,1,-2,-1,-2,-2,-1};
int n,m,ans,k;
void dfs(int x,int y){
	if(k==n*m){
		ans++;
		return;
	}
	for(int i=0;i<8;i++){
		int nx=x+g[i][0];
		int ny=y+g[i][1];
		if(nx>= 0 && nx<n && ny>=0 && ny<m && !vis[nx][ny]){
			vis[nx][ny]=1;
			k++;
			dfs(nx,ny);
			k--;
			vis[nx][ny]=0;
		}
	}
}
int main(){
	int t,x,y;
	cin>>t;
	while(t--){
		cin>>n>>m>>x>>y;
		ans=0;
		memset(vis,0,sizeof(vis));
		k=1;
        vis[x][y]=1;
		dfs(x,y);
		cout<<ans<<endl;
	}
	return 0;
}

疾病预防系统

描述

某国新研发了一套疾病预防系统,传染病爆发时,监测系统会把下面反应上来的情况在系统中形成一个矩形阵列,由数字 0 到 9 组成,数字 1 到 9 代表染病居民,求出感染区域的个数。一个感染区域为染病居民上下左右为非零数字的连通区域。

输入描述

第一行为两整数 m,n (m行,n列) (0<m,n≤100)
从第二行开始是一个 m×n 的矩阵

输出描述

只有一行为矩阵中的感染区域的个数。

用例输入 1

10 30
000110100111000010011000100010
100111111000101001001000100110
011010110000001001011100001010
011111100101111000011101010010
010001011100110101010111111100
110100010011001010101101110101
101001010010101001000111101001
010100110111110111111101100010
000111100100110101001011100100
110101100101101100110000101100
用例输出 1

28

#include <bits/stdc++.h>
using namespace std;
char mp[105][105];
int g[4][2]={-1,0,1,0,0,-1,0,1};
int n,m,ans;
void dfs(int x,int y){
	mp[x][y]='0';
	for(int i=0;i<4;i++){
		int nx=x+g[i][0];
		int ny=y+g[i][1];
		if(nx >0 && nx <=m && ny >0 && ny <=n && mp[nx][ny]!='0'){
			dfs(nx,ny);
		}
	}
}
int main(){
	cin>>m>>n;
	for(int i=1;i<=m;i++){
		for(int j=1;j<=n;j++){
			cin>>mp[i][j];
		}
	}
	for(int i=1;i<=m;i++){
		for(int j=1;j<=n;j++){
			if(mp[i][j]!='0'){
				dfs(i,j);
				ans++;
			}
		}
	}
	cout<<ans;
	return 0;
}

迷宫

描述

有 1 个 n×n 的迷宫方格,在方格内,“0”表示可以走,“1”表示是障碍物,不能行走,有个人在放个左上角起点( 1 , 1 )的位置,他在迷宫内可以向当前位置的上、下、左、右四个方向行走,问能不能在迷宫里走到终点右下角( n,n ),保证起点和终点均为“0”,走的时候不能走出迷宫的四周。

输入描述

输入第一行为 n( ≤n≤10 ),表示 n×n 的方格,接下来有 n 行,每行 n 个整数, 0 表示可以行走,1 表示不能行走,每个整数之间有个空格。

输出描述

如果可以走到终点,输出“YES”,否则输出“NO”

用例输入 1

3
0 0 1
1 0 0
0 1 0
用例输出 1

YES

#include <bits/stdc++.h>
using namespace std;
int mp[12][12],vis[12][12];//第一步:申明变量
int n,flag=0;
int dx[4]={-1,0,1,0};//新坐标x方向
int dy[4]={0,1,0,-1};//新坐标y方向
//第四步:搜索
void dfs(int x,int y){
    if(x==n && y==n){//a:判断递归边界
        flag=1;
        return;
    }
    //b:向几个方向搜索
    for(int i=0;i<4;i++){
        int xx=x+dx[i];//得到新坐标
        int yy=y+dy[i];
        //c:判断新坐标满足要求吗
        if(xx>0 && xx<=n && yy>0 && yy<=n){
            if(mp[xx][yy]==0 && vis[xx][yy]==0){
                vis[xx][yy]=1;//d:满足即走过
                dfs(xx,yy);//e:以当前点作为起点继续搜索
            }
        }
    }
}
int main(){
    //第二步:输入数据
	cin>>n;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			cin>>mp[i][j];
		}
	}
    //第三步:标记起点走过
	vis[1][1]=1;
    dfs(1,1);//第四步:搜索调用
    //第五步:输出结果
    if(flag==true) cout<<"YES";
    else cout<<"NO";
	return 0;
}

统计线路

描述

一个N*N的迷宫方格,在方格内“0”表示可以走,“1”表示不能行走,“2”表示宝藏。现在从左上角(1,1)的位置进入迷宫寻找宝藏。统计有多少条线路可以找到宝藏(每条线路经过的格子只能访问1次)。

输入描述

第一行,一个正整数N(2<N<6),后面包含N*N行由0,1,2组成的矩阵,其中0表示可以走,1表示不能走,2表示宝藏的位置。

输出描述

一行,一个整数,表示可以找到宝藏的线路。

用例输入 1

5
0 0 1 1 0
1 0 0 0 0
0 0 0 0 2
0 1 1 0 0
0 0 0 1 0
用例输出 1

12

#include <bits/stdc++.h>
using namespace std;
int mp[15][15],vis[15][15];
int dx[4]={0,1,0,-1};
int dy[4]={1,0,-1,0};
int ans=0,n;
void dfs(int x,int y){
	if(mp[x][y]==2){
		ans++;
		return;
	} 
	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 <= n) {
			if (mp[nx][ny] !=1 && !vis[nx][ny]) {
			vis[nx][ny] = 1;
			dfs(nx,ny); 
			vis[nx][ny]=0;
			}
		}
	}
}
int main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			cin>>mp[i][j];
		}
	}
	if(mp[1][1]==1){
		cout<<0;
		return 0;
	}
	vis[1][1]=1;
	dfs(1,1);
	cout<<ans;
	return 0;
} 
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值