搜索专题(未完)

· · 个人记录

搜索做题总结

前言:

因为搜索一直被众OIer称为万能算法——很多题都能用搜索得部分分,所以...所以...嗯,还是重新再刷一遍搜索的题,找找感觉吧!希望在之后的大小比赛考试中能够发挥出来quq

搜索提单——从基础到提高(未完):

-- 洛谷P1451 求细胞个数

-- 洛谷P1141 01迷宫

-- 洛谷P1683 入门 (此“入门”非彼“入门”,虽然都还挺简单的)

-- 洛谷P1157 组合的输出

-- 洛谷P1036 选数

-- 洛谷P1443 马的遍历

-- 洛谷P1746 离开中山路

-- 洛谷P2372 yyy2015c01挑战算周长

(题目有点长..我这个蒟蒻读了两遍题才读懂QAQ但是题很简单)

其实这些题很多都是有相似的地方的,而这些相似的地方就是搜索的基础。我们可以把这里作为突破口,然后清晰思路,更利于编程。

常见的搜索基础类型:“搜索求联通块”、“n个数选k个数”

-- 洛谷P2360 地下城主

(虽然标签是普及-,但是我认为比马的遍历那些题会难一点?大概还是因为我蒻)

-- 洛谷P2298 Mzc和男家丁的游戏

-- 洛谷P1332 血色先锋队

-- 洛谷P1434 滑雪

-- 洛谷P1019 单词接龙

-- 洛谷P1032 字串变换

-- 洛谷P3956 棋盘

(这道题我用广搜没有搞出来,就是太菜,然后使用了WS同学的深搜,这里就推荐一篇他的题解:棋盘 题解)

部分题目思路:

-- 求细胞个数、01迷宫、入门、yyy2015c01挑战算周长:“搜索求联通块”

-- 组合的输出、选数:DFS,“n个数选k个数”

-- 马的遍历、离开中山路:BFS求最短距离

-- 地下城主:三维搜索+求最短距离,注意一下数组是先层再行再列(我栽在这1hQAQ),后面给出该题的代码

-- Mzc和男家丁的游戏、血色先锋队:求最短距离

-- 滑雪、单词接龙、字串变换、棋盘:之后会给出代码

部分题目代码(题解以后再补充qwq):

inline void bfs(int x,int y) { a[x][y]='0'; for(register int i=0;i<4;i++) { int xx=x+dx[i]; int yy=y+dy[i]; if(xx>n||xx<1||yy>m||yy<1||a[xx][yy]=='0') continue; bfs(xx,yy); } }

int main() { scanf("%d%d",&n,&m); for(register int i=1;i<=n;i++) { for(register int j=1;j<=m;j++) { cin>>a[i][j]; } } for(register int i=1;i<=n;i++) { for(register int j=1;j<=m;j++) { if(a[i][j]!='0') { ans++; bfs(i,j); } } } printf("%d",ans); return 0; }

- 选数
```cpp
#include <bits/stdc++.h>
using namespace std;
int n,r,sum,ans,num[5000001];

inline bool check(int tot) {
    for(register int i=2;i*i<=tot;i++) {
        if(tot%i==0) return false;
    }
    return true;
}

inline void dfs(int now,int k) {
    for(register int i=k;i<=n;i++) {
        sum+=num[i];
        if(now==r) {
            if(check(sum)) ans++;
        }
        else dfs(now+1,i+1);
        sum-=num[i];
    }
}

int main() {
    scanf("%d%d",&n,&r);
    for(register int i=1;i<=n;i++) {
        scanf("%d",&num[i]);
    }
    dfs(1,1);
    printf("%d",ans);
    return 0;
}

struct node { int x,y,st; } q[160005];

inline void bfs(int xx,int yy) { pd[xx][yy]=1; int front=1,tail=1; q[front].x=xx; q[front].y=yy; q[front].st=0; while(front<=tail) { for(register int i=0;i<8;i++) { int xs=q[front].x+dx[i]; int ys=q[front].y+dy[i]; if(xs>=1&&xs<=n&&ys>=1&&ys<=m&&pd[xs][ys]==0) { tail++; q[tail].x=xs; q[tail].y=ys; q[tail].st=q[front].st+1; ans[xs][ys]=q[tail].st; pd[xs][ys]=1; } } front++; } }

int main() { memset(ans,-1,sizeof(ans)); scanf("%d%d%d%d",&n,&m,&sx,&sy); ans[sx][sy]=0; bfs(sx,sy); for(register int i=1;i<=n;i++) { for(register int j=1;j<=m;j++) { printf("%-5d",ans[i][j]); } puts(""); } return 0; }

- 地下城主
```cpp
#include <bits/stdc++.h>
using namespace std;
int L,R,C,sx,sy,sh,ex,ey,eh,sum,ans;
char a[31][31][31];
int dx[6]={0,1,0,-1,0,0};
int dy[6]={1,0,-1,0,0,0};
int dh[6]={0,0,0,0,1,-1};

struct node {
    int x,y,h,st;
} q[100001];

inline void bfs(int xx,int yy,int hh) {
    a[hh][xx][yy]='#'; //一定要注意先层再行再列!
    int front=1,tail=1;
    q[front].x=xx;
    q[front].y=yy;
    q[front].h=hh;
    q[front].st=0;
    while(front<=tail) {
        for(register int i=0;i<6;i++) {
            int xs=q[front].x+dx[i];
            int ys=q[front].y+dy[i];
            int hs=q[front].h+dh[i];
            if(xs>=1&&xs<=R&&ys>=1&&ys<=C&&hs>=1&&hs<=L&&a[hs][xs][ys]!='#') {
                tail++;
                q[tail].x=xs;
                q[tail].y=ys;
                q[tail].h=hs;
                q[tail].st=q[front].st+1;
                if(xs==ex&&ys==ey&&hs==eh) {
                    printf("Escaped in %d minute(s).",q[tail].st);
                    return ;
                }
                a[hs][xs][ys]='#';
            }
        }
        front++;
    }
    puts("Trapped!");
}

int main() {
    scanf("%d%d%d",&L,&R,&C);
    for(register int i=1;i<=L;i++) {
        for(register int j=1;j<=R;j++) {
            for(register int k=1;k<=C;k++) {
                cin>>a[i][j][k];
                if(a[i][j][k]=='S') {
                    sx=j;
                    sy=k;
                    sh=i;
                }
                if(a[i][j][k]=='E') {
                    ex=j;
                    ey=k;
                    eh=i;
                }
            }
        }
    }
    bfs(sx,sy,sh);
    return 0;
}

struct node { int x,y,st; }q[2500005];

inline void bfs(int tot) { int front=1,tail=tot; while(front<=tail) { for(register int i=0;i<4;i++) { int xx=q[front].x+dx[i]; int yy=q[front].y+dy[i]; if(xx>=1&&xx<=n&&yy>=1&&yy<=m&&pd[xx][yy]==0) { pd[xx][yy]=1; tail++; q[tail].x=xx; q[tail].y=yy; q[tail].st=q[front].st+1; ans[xx][yy]=q[tail].st; } } front++; } }

int main() { scanf("%d%d%d%d",&n,&m,&a,&b); for(register int i=1;i<=a;i++) { scanf("%d%d",&x,&y); q[i].x=x; q[i].y=y; q[i].st=0; pd[x][y]=1; ans[x][y]=0; } bfs(a); for(register int i=1;i<=b;i++) { scanf("%d%d",&x,&y); printf("%d\n",ans[x][y]); } return 0; }

- 滑雪
```cpp
#include <bits/stdc++.h>
using namespace  std;
int c,r,sum=0,a[101][101],f[101][101];
int dx[5]={0,0,-1,0,1};
int dy[5]={0,1,0,-1,0};
inline void dfs(int x,int y) {
    f[x][y]=1;
    int tot=0,ans=1;
    for(int i=1;i<=4;i++) {
        int xx=x+dx[i];
        int yy=y+dy[i];
        if(xx>=1&&xx<=r&&yy>=1&&yy<=c&&a[xx][yy]>a[x][y]) {
            if(f[xx][yy]==0) {
                dfs(xx,yy);
            }
            f[x][y]=max(f[x][y],f[xx][yy]+1);
        }
    }
}
int main() {
    cin>>r>>c;
    for(int i=1;i<=r;i++) {
        for(int j=1;j<=c;j++) {
            cin>>a[i][j];
        }
    }
    for(int i=1;i<=r;i++) {
        for(int j=1;j<=c;j++) {
            if(f[i][j]==0) dfs(i,j);
            sum=max(sum,f[i][j]);
        }
    }
    cout<<sum;
    return 0;
}

To be continue...