Zeta_c 搜索技术

递归和排列

子集生成和组合

BFS

BFS广度优先搜索或者宽度优先搜索

BFS和队列

BFS=队列
在这里插入图片描述

在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;

char room[23][23];
int dir[4][2] = {{-1, 0},{0,-1},{1,0},{0,1}};
int Wx, Hy, num;
#define CHECK(x,y)(x<Wx && x>=0 && y>=0 && y<Hy)
struct node{int x,y;};
void BFS(int dx, int dy){
    num = 1;
    queue<node>q;
    node start, next;
    start.x = dx;
    start.y = dy;
    q.push(start);
    while(!q.empty()){
        start = q.front();
        q.pop();
        //cout<<start.x<<' '<<start.y<<endl;
        for(int i = 0; i < 4; i++){ //按左上右下顺时针搜索
            next.x = start.x + dir[i][0];
            next.y = start.y + dir[i][1];
            if(CHECK(next.x,next.y) && room[next.x][next.y] == '.'){
                room[next.x][next.y] = '#'; //进队后标记已处理
                num++;
                q.push(next);
            }
        }
    }
}

int main(){
    int x, y, dx, dy;
    while(cin>> Wx>> Hy){ //Wx行,Hy列
        if(Wx == 0 && Hy == 0) break; //结束
        for(y = 0; y<Hy;y++){
            for(x = 0; x<Wx;x++){
                cin>> room[x][y];
                if(room[x][y] == '@'){ //读入起点
                    dx = x;
                    dy = y;
                }
            }
        }
        num = 0;
        BFS(dx, dy);
        cout<<num<<endl;
    }
    return 0;
}

输入
5 4
....#
.....
#@...
.#..#
0 0
输出
15

例题

poj 3278
poj 1426
poj 3126
poj 3414
hdu 1240
hdu 4460

八数码问题和状态图搜索

在这里插入图片描述
在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;

const int LEN = 362880;
struct node{
    int state[9];
    int dis;
} ;
int dir[4][2] = {{-1, 0},{0,-1},{1,0},{0,1}};

int visited[LEN] = {};
int start[9];
int goal[9];
long int factory[] = {1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880};

bool Cantor(int str[], int n){
    long result = 0;
    for(int i = 0; i < n; i++){
        int counted = 0;
        for( int j = i+1; j < n; j++){
            if(str[i] > str [j]) ++counted;
        }
        result += counted * factory[n-i-1];
    }
    if(!visited[result]){
        visited[result] = 1;
        return 1;
    }
    else return 0;
}

int bfs(){
    node head;
    memcpy(head.state,start,sizeof(head.state));
    head.dis=0;
    queue<node> q;
    Cantor(head.state,9);
    q.push(head);


    while(!q.empty()){
        head=q.front();
        q.pop();
        int z;
        for(z = 0; z< 9;z++)
            if(head.state[z] == 0)break;
        int x = z%3;
        int y = z/3;
        for(int i = 0; i < 4; i++){
            int newx = x+dir[i][0];
            int newy = y+dir[i][1];
            int nz = newx + 3 * newy;
            if(newx >= 0&& newx<3 &&newy>=0&&newy<3){
                node newnode;
                memcpy(&newnode, &head, sizeof(struct node));
                swap(newnode.state[z],newnode.state[nz]);
                newnode.dis++;
                if(memcmp(newnode.state,goal,sizeof(goal))==0) return newnode.dis;
                if(Cantor(newnode.state, 9)) q.push(newnode);
            }
        }
    }
    return -1;
}

int main(){
    for(int i = 0; i < 9; i++) cin>>start[i];
    for(int i = 0; i < 9; i++) cin>>goal[i];
    int num = bfs();
    if(num != -1) cout<<num<<endl;
    else cout<<"Impossible"<<endl;
    return 0;
}

poj 1077;

BFS和A*算法

在搜索最短距离时,如果(障碍物或相邻点距离不同)绕路更近,A*算法优化了BFS。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

双向广搜

双向广搜是BFS的增强版
在这里插入图片描述

DFS

DFS和递归

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

POJ 3984 迷宫问题

题目:

Description

定义一个二维数组:

int maze[5][5] = {
0, 1, 0, 0, 0,
0, 1, 0, 1, 0,
0, 0, 0, 0, 0,
0, 1, 1, 1, 0,
0, 0, 0, 1, 0,
};
它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要求编程序找出从左上角到右下角的最短路线。
Input
一个5 × 5的二维数组,表示一个迷宫。数据保证有唯一解。

Output
左上角到右下角的最短路径,格式如样例所示。

Sample Input
0 1 0 0 0
0 1 0 1 0
0 0 0 0 0
0 1 1 1 0
0 0 0 1 0

Sample Output
(0, 0)
(1, 0)
(2, 0)
(2, 1)
(2, 2)
(2, 3)
(2, 4)
(3, 4)
(4, 4)

思路:
迷宫是一个5 × 5的二维数组,搜索起来不会很复杂,也不会超时。从左上角(0, 0)位置开始,上下左右进行搜索,可以定义一个方向数组,代表上下左右四个方向,使用方向数组,可以使一个点上下左右移动。对于数组中的每个元素用结构体来存储,除了有x,y成员外,还要定义pre成员,用来表示从左上角到右下角的最短路径中每个元素的前一个元素的下标,即保存路径,方便后面的输出。通过广度搜索借助队列进行操作,当中要注意1.搜索的元素是否在迷宫内;2.是否可行(其中1是墙壁不能走,0可以走)。我们可以把已走过的路标记为1,这样能保证路径最短(因为广度优先搜索,只会离初始点的步数一步步增多。如果之后发现遇到了已走过的点,那肯定是从之前已走过的点那边走最短,而不是从之后发现的点走最短啊),直到搜索到右下角(4, 4),问题就解决了。输出路径即可。


水池数目

#include<bits/stdc++.h>
using namespace std;
int mp[100][100],m,n,t;
int dir[4][2]={{-1,0},{0,-1},{1,0},{0,1}};
void dfs(int dx,int dy){
    mp[dx][dy]=0;
    for(int i = 0; i<4;i++){
        int nx=dx+dir[i][0];
        int ny=dy+dir[i][1];
        if (nx>=0 && nx <n && ny>=0 && ny<m && mp[nx][ny]==1){
            mp[nx][ny] = 0;
            dfs(nx,ny);
        }
    }
}
int main(){
    cin>>t;
    while(t--){
        cin>>m>>n;
        for(int i = 0; i < m; i++){
            for(int j = 0; j < n; j++) cin>>mp[i][j];
        }
        int count = 0;
         for(int i = 0; i < m; i++){
            for(int j = 0; j < n; j++){
                if(mp[i][j] == 1){
                    dfs(i, j);
                    count++;
                }
            }
        }
        cout<<count<<endl;
    }
    return 0;
}

图像有用区域

树的前序中序后序遍历

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值