【深度优先算法】
沿着某条路径遍历,直到末端,然后回溯,再遍历另一条路径(走没有走过的岔路口)做同样的遍历,直到所有的节点都被访问,即回溯到源节点并且源节点已无未被访问的子节点。
库克船长的宝藏
库克船长在无名岛上埋藏了一些宝藏,找到它们需要路过一片沼泽地,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;
}