2021-02-06

本文详细介绍了深度优先搜索(DFS)和广度优先搜索(BFS)两种基本图遍历算法。通过排列组合、最短路径问题和走迷宫等实例,展示了它们在解决实际问题中的应用。DFS适用于探索深度,BFS则适用于寻找最短路径。此外,还提及了最短路算法,包括多源最短路和单源最短路的概念和实现。
摘要由CSDN通过智能技术生成
搜索
  • 通过不停的试探去寻找解的一种算法, 更像是一种方法。 暴力搜, 深搜, 广搜。
  1. 深搜

例题一、 排列组合问题:
深搜解法:

#include <iostream>
#include <algorithm>

using namespace std;
int a[10], book[10];
int n;
void dfs(int st)
{
    if(st == n + 1){
        for(int i = 1; i <= n; i ++) cout << a[i] << " ";
        cout << endl;
        return ;
    }
    for(int i = 1; i <= n; i ++){
        if(!book[i]){
            book[i] = 1;
            a[st] = i;
            dfs(st + 1);
            book[i] = 0;
        }
    }

}
int main()
{
    cin >> n;
    dfs(1);
    return 0;
}

例题二、

#include <iostream>
#include <algorithm>

using namespace std;
int a[1000];
int n, sum;

void dfs(int st, int k, int m)
{
    if(st == k + 1){
        if(m == 0){
            printf("%d=%d", n, a[1]);
            for(int i = 2; i <= k; i ++) printf("+%d", a[i]);
            printf("\n");
            sum ++;
        }
        return ;
    }
    for(int i = a[st - 1]; i <= m / (k - st + 1); i ++){
        a[st] = i;
        dfs(st + 1, k, m - i);
    }
}
int main()
{
    cin >> n;
    a[0] = 1;
    for(int i = 1; i <= n; i ++){
        dfs(1, i, n);
    }
    cout << sum;
    return 0;
}

例题三、走迷宫问题

#include <iostream>
#include <algorithm>

using namespace std;
typedef long long ll;
ll n, m, minn = 0x3fffffff;
ll a[505][505], book[505][505];
ll dx[5] = {0, 1, 0, -1};
ll dy[5] = {1, 0, -1, 0};

void dfs(int x, int y, ll st)
{
    ll tx, ty, k;
    if(x == n - 1 && y == n - 1){
        if(st < minn) minn = st;
        return ;
    }
    for(k = 0; k < 4; k ++){
        tx = x + dx[k];
        ty = y + dy[k];
        if(tx < 0 || tx > n - 1 || ty < 0 || ty > n - 1) continue;
        if(book[tx][ty] == 0 &&a[tx][ty] == 0){
            book[tx][ty] = 1;
            dfs(tx, ty, st + 1);
            book[tx][ty] = 0;
        }
    }
}
int main()
{
    scanf("%lld", &n);
    for(ll i = 0; i < n; i++){
        for(ll j = 0; j < n; j ++){
            scanf("%lld", &a[i][j]);
        }
    }
    book[0][0] = 1;
    dfs(0, 0, 0);
    printf("%lld\n", minn);
    return 0;
}

  1. 广搜
#include <iostream>
#include <algorithm>

using namespace std;
int arr[501][501];
int book[501][501];
int dx[5] ={0, 1, 0, -1};//规定四个方向
int dy[5]= {1, 0, -1, 0};
struct f {
    int x;
    int y;
    int s;
}map[2500];
int n;
void bfs()
{
    int tail = 1, head = 1;
    map[tail].x = 0, map[tail].y = 0;
    map[tail].s = 0;
    book[0][0] = 1;
    tail++;
    while (head < tail)
    {
        int k = 0;
        for (int i = 0; i < 4; i++){
            int nx = map[head].x + dx[i];
            int ny = map[head].y + dy[i];
            if (nx<0 || nx>n - 1 || ny<0 || ny>n - 1)
                continue;
            if (book[nx][ny] == 0 && arr[nx][ny] == 0){
                book[nx][ny] = 1;
                map[tail].x = nx;
                map[tail].y = ny;
                map[tail].s = map[head].s + 1;
                tail++;
            }
            if (nx == n-1 && ny == n-1){
                k = 1;
                cout << map[tail - 1].s;
                break;
            }
        }   
        if (k == 1) break;
        head++;

    }
}
int main(void)
{
    cin >> n;
    for (int i = 0; i < n; i++){
        for (int j = 0; j < n; j++)
            scanf("%d", &arr[i][j]);
    }
    bfs();
    return 0;
}
最短路
  1. 多源最短路
  • 概念:任意两点的最短距离
  • 思想:用每一个点作为中转点, 进行“松弛” 操作。
#include <iostream>

using namespace std;
int a[105][105], b[10005];
int m, n;

int main()
{
    cin >> n >> m;
    for(int i = 1; i <= m; i ++) cin >> b[i];
    for(int i = 1; i <= n; i ++){
        for(int j = 1; j <= n; j ++){
            cin >> a[i][j];
        }
    }
    for(int k = 1; k <= n; k++){
        for(int i = 1; i <= n; i ++){
            for(int j = 1; j <= n; j ++){
                if(a[i][j] > a[i][k] + a[k][j])
                    a[i][j] = a[i][k] + a[k][j];
            }
        }
    }
    int ans = 0;
    for(int i = 1; i < m; i ++) ans += a[b[i]][b[i + 1]];
    cout << ans;
}
  1. 单源最短路
  • 某一个点到其他点的最短距离
  • 思想:把所有点分为两个阵营, 一个为已求出最短距离阵营,另一个为未求出最短距离阵营。把每一个未求出最短距离阵营的点依次加入到求出最短距离阵营(每次找的是离求出最短距离阵营最近的点),并用这个点作为中转点,进行“松弛“操作。
#include <iostream>

using namespace std;
int a[505][505];
int dis[505];
int book[505];
const int inf = 0x3f3f3f3f;
int n, m;
void f()
{
    book[1] = 1;
    for(int i = 1; i <= n - 1; i ++){
        int minn = inf;
        int u;
        for(int j = 1; j <= n; j++){
            if(book[j] == 0 && dis[j] < minn){
                minn = dis[j];
                u = j;
            }
        }
        book[u] = 1;

        for(int j = 1; j <= n; j ++){
            if(book[j] == 0 && dis[j] > dis[u] + a[u][j])
                dis[j] = dis[u] + a[u][j];
        }

    }
}
int main()
{

    cin >> n >> m;
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            if(i == j) a[i][j] = 0;
            else a[i][j] = inf;
        }
    }
    while(m --){
        int x, y, z;
        cin >> x >> y >> z;
        if(a[x][y] > z) 
            a[x][y] = z;
    }
    for(int i = 1; i <= n; i ++){
        dis[i] = a[1][i];
    }
    f();
    if(dis[n] < inf)
        cout << dis[n] ;
    else cout << -1;

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值