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点

点击查看代码

posted @ 2024-03-31 13:37  HelloHeBin  阅读(32)  评论(0编辑  收藏  举报