1.1791 多少块水洼
有一块 N×M 的土地,雨后积起了水,有水标记为‘W’,干燥为‘.’。八连通的积水被认为是连接在一起的。请求出院子里共有多少水洼?
输入描述
第一行为 N,M (1≤N,M≤100)。
下面为 N×M的土地示意图。
输出描述
一行,共有的水洼数。
样例输入 1
10 12 W........WW. .WWW.....WWW ....WW...WW. .........WW. .........W.. ..W......W.. .W.W.....WW. W.W.W.....W. .W.W......W. ..W.......W.
样例输出 1
3
搜索模板题(八个方向)
AC代码:
#include<bits/stdc++.h>
using namespace std;
int vis[105][105];
char mp[105][105];
int n,m,ans;
int dx[8] = {0,1,1,1,0,-1,-1,-1};
int dy[8] = {1,1,0,-1,-1,-1,0,1};
void dfs(int x,int y)
{
for(int i=0;i<8;i++){
int nx = x+dx[i];
int ny = y+dy[i];
if(nx>=0 && nx<n && ny>=0 && ny<m && mp[nx][ny]=='W' && vis[nx][ny]==0){
vis[nx][ny] = 1;
dfs(nx,ny);
}
}
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>n>>m;
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
cin>>mp[i][j];
}
}
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
if(mp[i][j]=='W'&& vis[i][j]==0){
ans++;
vis[i][j] = 1;
dfs(i,j);
}
}
}
cout<<ans;
return 0;
}
2.3090 走迷宫
描述
一天童童在森林里探险的时候不小心走入了一个迷宫,迷宫可以看成是由 n×n (1≤n≤100) 的格点组成,每个格点只有 2 种状态,“.”和“#”,前者表示可以通行,后者表示不能通行。童童处在某个格点时,他只能移动到东西南北四个方向之一的相邻格点上,童童想要从点 A 走到点 B,问在走不出迷宫的情况下能不能办到。注:如果起点或者终点有一个不能通行(为#),则看成无法办到。
输入描述
第一行是一个整数 n,表示迷宫的规模是 n×n。接下来是一个 n 的矩阵,矩阵中的元素为“.”或者“#”。最后一行是 4 个整数,前两个整数描述点 A 的坐标,后两个整数描述点B的坐标。注:第一行第一列元素坐标为(0,0)。
输出描述
一个整数,能办到输出“yes”,否则输出“no”。
样例输入 1
3 ..# ..# #.. 0 0 2 2
样例输出 1
yes
提示
数据范围与提示
1≤n≤100
模板题(AC代码)
#include<bits/stdc++.h>
using namespace std;
bool vis[105][105],f=0;
int n,x,y,startx,starty;
char c[105][105];
int dx[4] = {1,0,-1,0},dy[4] = {0,1,0,-1};
void dfs(int x1,int y1)
{
if(x1==x && y1==y)
{
f = 1;
}
for(int i=0;i<4;i++)
{
int nx = x1+dx[i];
int ny = y1+dy[i];
if(nx>=0 && nx<n && ny>=0 && ny<n && vis[nx][ny]==0 && c[nx][ny]=='.')
{
vis[nx][ny] = 1;
dfs(nx,ny);
}
}
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>n;
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
cin>>c[i][j];
}
}
cin>>startx>>starty>>x>>y;
if(c[startx][starty]=='#' or c[x][y]=='#')
{
cout<<"no";
return 0;
}
else
{
dfs(startx,starty);
}
if(f==1) cout<<"yes";
else cout<<"no";
return 0;
}
3.2937 八个方向统计线路
已知山洞里面是由许多房间组成的迷宫,每个房间可以通往周围八个房间,迷宫大小是一个N*N的正方形,其中有一些蝙蝠堵路。现在从起始(1,1)的位置进入洞穴寻找宝藏(只有一个宝箱),统计有多少条线路可以找到宝藏。
输入描述
第一行是一个正整数N(2<N<6),后面包含N*N行由0,1,2组成的矩阵,其中0表示可以走,1表示蝙蝠,2表示宝藏的位置。
输出描述
一行,一个整数,表示可以找到宝藏的线路。
样例输入 1
6 0 0 1 1 0 0 1 0 0 1 0 0 0 0 0 1 2 0 0 1 1 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0
样例输出 1
0
样例输入 2
2 0 0 0 2
样例输出 2
5
AC代码:
#include<bits/stdc++.h>
using namespace std;
int vis[11][11],mp[15][15],ans;
int n;
int dx[8] = {0,1,1,1,0,-1,-1,-1};
int dy[8] = {1,1,0,-1,-1,-1,0,1};
void dfs(int x,int y)
{
if(mp[x][y]==2)
{
ans++;
return ;
}
for(int i=0;i<8;i++)
{
int nx = x+dx[i];
int ny = y+dy[i];
if(nx>0&&nx<=n&ny>0&&ny<=n&&vis[nx][ny]==0&&mp[nx][ny]!=1)
{
vis[nx][ny] = 1;
dfs(nx,ny);
vis[nx][ny] = 0;
}
}
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
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;
}
4.2936 八个方向
描述
已知山洞里面是由许多房间组成的迷宫,每个房间可以通往周围八个房间,迷宫大小是一个N*N的正方形,其中有一些蝙蝠堵路。现在从起始(1,1)的位置进入洞穴寻找宝藏(已有一个宝箱),如果可以找到宝藏输出YES,否则输出NO。
输入描述
第一行是一个正整数N(2<N ≤10),后面包含N*N行由0,1,2组成的矩阵,其中0表示可以走,1表示蝙蝠,2表示宝藏的位置。
(注意:第一个房间没有蝙蝠)
输出描述
一行,找到宝藏输出YES,否则输出NO 。
样例输入 1
6 0 0 1 1 0 0 1 0 0 1 0 0 0 0 0 1 2 0 0 1 1 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0
样例输出 1
NO
样例输入 2
5 0 0 0 0 0 0 0 1 1 1 0 0 0 1 0 0 1 0 1 2 0 0 0 0 1
样例输出 2
YES
AC代码
#include<bits/stdc++.h>
using namespace std;
int vis[11][11],mp[15][15];
int n;
bool f;
int dx[8] = {0,1,1,1,0,-1,-1,-1};
int dy[8] = {1,1,0,-1,-1,-1,0,1};
void dfs(int x,int y)
{
if(mp[x][y]==2)
{
f = 1;
return ;
}
for(int i=0;i<8;i++)
{
int nx = x+dx[i];
int ny = y+dy[i];
if(nx>0&&nx<=n&ny>0&&ny<=n&&vis[nx][ny]==0&&mp[nx][ny]!=1)
{
vis[nx][ny] = 1;
dfs(nx,ny);
}
}
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
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<<"NO";
return 0;
}
vis[1][1] = 1;
dfs(1,1);
if(f) cout<<"YES";
else cout<<"NO";
return 0;
}
5.6604 地图找车
有一个 n×m 的地图 (1<n,m<20),地图上 “.” 表示可以通行, “X” 表示不可通行,"*"表示车所在的位置。从地图左上角开始寻找车,如果能找到输出 YES
,否则输出 NO
。注意:第一行有可能不能通行。
输入描述
第一行 n 和 m ,两者均不大于 20 ,n 表示行数, m 表示列数。接下来 n 行, 每行包含 m 个字符: “.” , “X” , “*”。
输出描述
找到车输出 YES
,否则输出 NO
。
样例输入 1
5 6 . . X . . . . . . X . . . . . X . . X . . . . . XXX . * .
样例输出 1
YES
提示
数据范围与提示
1<n,m<20
广搜(AC代码)
#include<bits/stdc++.h>
using namespace std;
struct node{
int x,y;
};
int vis[105][105];
int n,m;
int dx[4] = {-1,0,1,0};
int dy[4] = {0,1,0,-1};
char mp[105][105];
queue<node> q;
void bfs(){
node a={1,1};
vis[1][1] =1;
q.push(a);
if(mp[1][1]=='X'){
cout<<"NO";
return;
}
while(q.size()){
node f = q.front();
q.pop();
if(mp[f.x][f.y]=='*'){
cout<<"YES";
return ;
}
for(int i=0;i<4;i++){
int nx = f.x+dx[i],ny = f.y+dy[i];
if(nx>0&&nx<=n&&ny>0&&ny<=m&&mp[nx][ny]!='X'&&vis[nx][ny]==0)
{
vis[nx][ny] = 1;
node r = {nx,ny};
q.push(r);
}
}
}
cout<<"NO";
}
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin>>mp[i][j];
}
}
bfs();
return 0;
}
6.2929 寻宝
侠盗 Hank 经过千难万险终于来到了恶人岛,为了拿到恶人岛的宝座去帮助穷人,Hank 先对恶人岛进行了侦查,发现恶人岛有一个迷阵,宝藏摆在了迷阵的深处。迷阵由 M×N 个方 格组成,有的方格内有可以发现 Hank 的守卫,而有的方格内则是安全。为了展现自己的实 力,Hank 决定不仅要拿走恶人岛的宝藏,还要给他们留一封信,告诉恶人自己有 g 种方法 找到宝藏。现在要求你来帮助他实现这个目标。
迷阵越大,守卫越多。
输入描述
输入有一组测试数据,以两个非零整数 N 和 M 开始,两者均不大于20。N表示迷阵行数, M表示迷阵列数。接下来有 N 行, 每行包含 M 个字符,不同字符分别代表不同含义:
- ‘@’:Hank 所在的位置;
- ‘.’:可以安全通行的方格;
- ‘#’:有守卫的方格;
- ‘*’:宝藏所在位置。
输出描述
一个整数 g,表示 Hank 有 g 种方法可以找到宝藏。如果他不可能找到宝藏, 则输出-1。
样例输入 1
8 8 .@##...# #....#.# #.#.##.. ..#.###. #.#...#. ..###.#. ...#.*.. .#...###
样例输出 1
4
样例输入 2
9 6 .#..#. .#.*.# .####. ..#... ..#... ..#... ..#... #.@.## .#..#.
样例输出 2
-1
AC代码
#include <iostream>
using namespace std;
int n,m,x1,y1,x2,y2;
bool flag;
int vis[25][25],ans;
int dx[4] = {1,0,-1,0},dy[4] = {0,1,0,-1};
char mp[25][25];
void dfs(int x,int y)
{
if(mp[x][y]=='*')
{
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<=m&&mp[nx][ny]!='#'&&vis[nx][ny]==0)
{
vis[nx][ny] = 1;
dfs(nx,ny);
vis[nx][ny] = 0;
}
}
}
int main() {
cin>>n>>m;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
cin>>mp[i][j];
if(mp[i][j]=='@')
{
x1 = i;
y1 = j;
}
}
}
vis[x1][y1] = 1;
dfs(x1,y1);
if(ans==0)
{
cout<<-1;
return 0;
}
cout<<ans;
return 0;
}
7.4143 中国象棋的马
描述
马在中国象棋以日字形规则移动,在一个 n×m 的棋盘中,每个格子内“0”表示可以走,“1”表示是障碍物不能走。马从左上角(1,1)位置出发,不思考掉绊马腿的情况,问能不能走到(ex,ey)格子。注意: (1,1)位置不为1。
输入描述
第一行为 n 和 m,表示 n×m 的棋盘(1<n,m≤10)。
接下来 n 行,每行 m 个整数,0 表示可以行走,1 表示不能行走,每个整数之间有个空格。
最后一行,表示要到达的格子位置。
输出描述
如果可以走到指定位置,输出“YES”,否则输出“NO”
样例输入 1
4 5 0 1 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 2 4
样例输出 1
YES
提示
数据范围与提示
1<n,m≤10
AC代码:
#include<bits/stdc++.h>
using namespace std;
int mp[11][11],vis[11][11];//mp:地图 vis:标记数组
int n,m,ex,ey;//n行m列 (ex,ey)到达点
bool flag=false;
int dx[8]={-2,-1,1,2,2,1,-1,-2};
int dy[8]={1,2,2,1,-1,-2,-2,-1};
void dfs(int x,int y){
if(x==ex && y==ey){
flag=true;
return ;
}
for(int i=0;i<8;i++){
int nx=x+dx[i];
int ny=y+dy[i];
if(nx>0&&nx<=n&&ny>0&&ny<=m && mp[nx][ny]==0 && vis[nx][ny]==0){
vis[nx][ny]=1;
dfs(nx,ny);
}
}
}
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++)
cin>>mp[i][j];
}
cin>>ex>>ey;
vis[1][1]=1; //标记(1,1)房间已搜索
dfs(1,1); //从(1,1)位置开始向周围搜索
if(flag) cout<<"YES";
else cout<<"NO";
return 0;
}
8.3089 探索迷宫
描述
有一个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
AC代码
#include <iostream>
using namespace std;
int n,m,x1,y1;
bool flag;
int vis[25][25];
int dx[4] = {1,0,-1,0},dy[4] = {0,1,0,-1};
int mp[25][25];
void dfs(int x,int y)
{
if(x==x1 && y==y1)
{
flag = 1;
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<=m&&mp[nx][ny]!=1&&vis[nx][ny]==0)
{
vis[nx][ny] = 1;
dfs(nx,ny);
}
}
}
int main() {
cin>>n>>m;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
cin>>mp[i][j];
}
}
if(mp[1][1]==1)
{
cout<<"NO";
return 0;
}
cin>>x1>>y1;
vis[1][1] = 1;
dfs(1,1);
if(flag) cout<<"YES";
else cout<<"NO";
return 0;
}