20240331_搜索练习
目录
P3207 Lake Counting
有一块N×M的土地,雨后积起了水,有水标记为‘W’,干燥为‘.’。八连通的积水被认为是连接在一起的。
请求出院子里共有多少水洼?
点击查看代码
#include<iostream>
using namespace std;
const int N=110;
char s[N][N];
bool st[N][N];
int n,m,ans;
int d[][2]={-1,-1, -1,0, -1,1, 0,-1, 0,1, 1,-1, 1,0,1,1};
void dfs(int x,int y){
st[x][y] = 1;
for(int i=0; i<8; i++){
int a=x+d[i][0], b=y+d[i][1];
if(a<0||a>=n||b<0||b>=m) continue;
if(s[a][b]=='.' || st[a][b]) continue;
dfs(a, b);
}
}
int main(){
cin>>n>>m;
for(int i=0; i<n; i++) cin>>s[i];
for(int i=0; i<n; i++)
for(int j=0; j<m; j++)
if(s[i][j]=='W' && !st[i][j]){ dfs(i,j); ans ++; }
cout<<ans;
return 0;
}
P896 仙岛求药
少年李逍遥的婶婶病了,王小虎介绍他去一趟仙灵岛,向仙女姐姐要仙丹救婶婶。孝顺的李逍遥闯进了仙灵岛,克服了千险万难来到岛的中心,发现仙药摆在了迷阵的深处。迷阵由M×N个方格组成,有的方格内有可以瞬秒李逍遥的怪物,而有的方格内则是安全。现在李逍遥想尽快找到仙药,显然他应避开有怪物的方格,并经过最少的方格,而且那里会有神秘人物等待着他。现在要求你来帮助他实现这个目标。
点击查看代码
#include<queue>
#include<cstring>
#include<iostream>
using namespace std;
const int N=22;
int n,m,ans,d[][2]= {-1,0, 1,0, 0,-1, 0,1};
char s[N][N];
int st[N][N];
struct T {
int x,y;
};
int sx,sy;
int bfs(int x,int y) {
memset(st, 0x00, sizeof st); // 8bit
queue<T> q;
q.push({x,y}), st[x][y] = 1;
while(q.size()) {
auto u = q.front();
q.pop();
x=u.x, y=u.y;
if(s[x][y]=='*') return st[x][y]-1;
for(int i=0; i<4; i++) {
int a=x+d[i][0], b=y+d[i][1];
if(a<0||a>=n||b<0||b>=m) continue;
if(s[a][b]=='#' || st[a][b]) continue;
q.push({a,b}), st[a][b] = st[x][y]+1;
}
}
return -1;
}
int main() {
// freopen("da.in", "r", stdin);
while(cin>>n>>m, n) {
if(n+m==0) break;
for(int i=0; i<n; i++) cin>>s[i];
for(int i=0; i<n; i++)
for(int j=0; j<m; j++)
if(s[i][j]=='@') {
sx=i, sy=j;
break;
}
int t = bfs(sx,sy);
cout<<t<<endl;
}
return 0;
}
P429 【基础】走迷宫
一个迷宫由 R行 C列格子组成,有的格子里有障碍物,不能走;有的格子是空地,可以走。 给定一个迷宫,求从左上角走到右下角最少需要走多少步(数据保证一定能走到)。只能在水平方向或垂直方向走,不能斜着走。
点击查看代码
#include<queue>
#include<cstring>
#include<iostream>
using namespace std;
const int N=50;
int n,m,ans,d[][2]= {-1,0, 1,0, 0,-1, 0,1};
char s[N][N];
int st[N][N];
struct T {
int x,y;
};
int sx,sy;
int bfs(int x,int y) {
memset(st, 0x00, sizeof st); // 8bit
queue<T> q;
q.push({x,y}), st[x][y] = 1;
while(q.size()) {
auto u = q.front(); q.pop();
x=u.x, y=u.y;
if(x==n-1 && y==m-1) return st[x][y];
for(int i=0; i<4; i++) {
int a=x+d[i][0], b=y+d[i][1];
if(a<0||a>=n||b<0||b>=m) continue;
if(s[a][b]=='#' || st[a][b]) continue;
q.push({a,b}), st[a][b] = st[x][y]+1;
}
}
return -1;
}
int main() {
while(cin>>n>>m) {
for(int i=0; i<n; i++) cin>>s[i];
int t = bfs(0,0);
cout<<t<<endl;
}
return 0;
}
P3206 Dungeon Master
这题是一个三维迷宫,其中用‘.’表示空地,‘#’表示障碍物,‘S’表示起点,‘E’表示终点,求从起点到终点的最小移动次数,解法和二维的类似,只是在行动时除了东南西北移动外还多了上下。可以上下左右前后移动,每次都只能移到相邻的空位,每次需要花费一分钟,求从起点到终点最少要多久。
- 分析
最少步数,考虑bfs,三维使用偏移数组
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=110;
char s[N][N][N];// s(z,x,y)
int st[N][N][N];// st(x,y,z)
int l,n,m,x,y,z;
int d[][3] = {1,0,0, -1,0,0, 0,1,0, 0,-1,0, 0,0,1, 0,0,-1};
struct T{
int x,y,z;
};
int bfs(){
memset(st, 0x00, sizeof st);
queue<T> q;
q.push({x,y,z}), st[x][y][z] = 1;
while(q.size()){
auto u=q.front(); q.pop();
x=u.x, y=u.y, z=u.z;
// cout<<"x,y,z: "<<x<<", "<<y<<", "<<z<<endl;
if(s[z][x][y]=='E') return st[x][y][z]-1;
for(int i=0; i<6; i++){
int a=x+d[i][0],b=y+d[i][1],c=z+d[i][2];
if(a<0||a>=n||b<0||b>=m||c<0||c>=l) continue;
if(st[a][b][c] || s[c][a][b]=='#') continue;
q.push({a,b,c}), st[a][b][c]=st[x][y][z]+1;
}
}
return -1;
}
int main() {
// freopen("da.in", "r", stdin);
while(cin>>l>>n>>m, l) {
for(int i=0; i<l; i++)
for(int j=0; j<n; j++) cin>>s[i][j];
for(int i=0; i<l; i++)
for(int j=0; j<n; j++)
for(int k=0; k<m; k++)
if(s[i][j][k]=='S') { z=i,x=j,y=k; break; }
int t = bfs();
if(t!=-1) cout<<"Escaped in "<<t<<" minute(s).\n";
else cout<<"Trapped!\n";
}
}
P2465 迷宫问题
用一个二维数组表示一个迷宫,其中1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走
编写程序,找出从左上角到右下角的最短路线
点击查看代码
#include<iostream>
#include<queue>
#define PII pair<int,int>
using namespace std;
const int N=10;
int s[N][N], st[N][N];
int n=5, d[][2]={-1,0, 1,0, 0,-1, 0,1};
PII path[N][N]; // path[a][b]= {x,y}
int bfs(int x,int y){
queue<PII> q; q.push({x,y}), st[x][y]=1;
while(q.size()){
auto u=q.front(); q.pop(); x=u.first, y=u.second;
if(x==1 &&y==1) return st[x][y];
for(int i=0; i<4; i++){
int a=x+d[i][0], b=y+d[i][1];
if(a<1||a>n||b<1||b>n ||s[a][b] || st[a][b]) continue;
q.push({a,b}), st[a][b]=st[x][y]+1;
path[a][b] = {x,y};
}
}
return -1;
}
int main(){
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++) cin>>s[i][j];
int ans = bfs(n,n);
int x=1,y=1;
while(1){
cout<<"("<<x-1<<", "<<y-1<<")"<<endl;
if(x==n && y==n) break;
auto u = path[x][y];
x = u.first; y = u.second;
}
return 0;
}
P3208 The Castle
点击查看代码
P952 【入门】算24点
点击查看代码