蓝桥杯高频考点(下)

一、图论,最短路径问题之朴素dijkstra算法

1.符号定义:共有N个点,找N点到1号点的最短距离;g[N][N]存储每条边的权重;dist[N]存储1号点到每个点的最短距离;st[N]存储每个点的最短路是否已经确定

2.步骤:

(1)先将所有的点到1号点的距离初始化为正无穷;

(2)每次从未标记的节点选择距离出发点最近的节点t并标记st[t]=true;

(3)更新j点到1号点的距离:dist[j] = min(dist[j], dist[t] + g[t][j]);

代码模板:

int g[N][N];  // 存储每条边
int dist[N];  // 存储1号点到每个点的最短距离
bool st[N];   // 存储每个点的最短路是否已经确定

// 求1号点到n号点的最短路,如果不存在则返回-1
int dijkstra()
{
    memset(dist, 0x3f, sizeof dist);//距离dist一开始初始化为无穷大
    dist[1] = 0;

    for (int i = 0; i < n - 1; i ++ )
    {
        int t = -1;// 在未标记(未确定最短路长度)的节点中找距离最小的点t
        for (int j = 1; j <= n; j ++ )
            if (!st[j] && (t == -1 || dist[t] > dist[j]))//st[j]==false代表j还没确定最短路
                t = j;//更新最短路长度的节点

        // 用t更新其他点的距离
        for (int j = 1; j <= n; j ++ )
            dist[j] = min(dist[j], dist[t] + g[t][j]);

        st[t] = true;
    }

    if (dist[n] == 0x3f3f3f3f) return -1;
    return dist[n];
}

二、图论,最短路径问题之floyd算法 

floyd算法有点像DP

代码模板:

初始化:
    for (int i = 1; i <= n; i ++ )
        for (int j = 1; j <= n; j ++ )
            if (i == j) d[i][j] = 0;
            else d[i][j] = INF;

// 算法结束后,d[a][b]表示a到b的最短距离
void floyd()
{
    for (int k = 1; k <= n; k ++ )//枚举一个个中间点k,不断更新i到j的距离
        for (int i = 1; i <= n; i ++ )
            for (int j = 1; j <= n; j ++ )
                d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
}

三、广度优先搜索BFS之迷宫

所谓广度优先,就是每次都尝试访问同一层的节点。 如果同一层都访问完了,再访问下一层。

迷宫问题的模板:(输入是迷宫,输出是最短距离):

#include<bits/stdc++.h>
#include<iostream>
using namespace std;
const int N=110; //n,m的数据范围均为100

int maze[N][N],dis[N][N],n,m; //maze[N][N]用来存储迷宫
//dis[x][y]用来存储(x,y)这一点到坐标原点的距离

queue <pair<int,int>> q;//q队列用来存储宽度优先搜素到的路径也就是走迷宫经过哪些点

int bfs()
{
    memset(dis,-1,sizeof dis); //将dis数组所有元素初始化为-1,表示这个点没有走过
    dis[0][0]=0; //位于原点(0,0)到原点的距离为0
    q.push({0,0}); //将原点入队

    int dx[4]={-1,0,1,0},dy[4]={0,1,0,-1}; //定义方向向量一共四个方向

    while(!q.empty()) //当队列非空时执行循环
    {
        auto t=q.front();//取出第一个点
        q.pop(); //插入一个位置的同时会弹出一个位置保证循环可以正常终止

        for(int i=0;i<4;i++) //遍历四个方向
        {
            int x=t.first+dx[i],y=t.second+dy[i]; //四个方向对应x,y坐标

            if(x>=0 && x<n && y<m && y>=0 && maze[x][y]==0 && dis[x][y]==-1 )
            //x,y都要在迷宫坐标范围内,并且(x,y)不是墙壁且没被走过
            {
                dis[x][y]=dis[t.first][t.second]+1; //走到下一个点的同时距离加1
                q.push({x,y}); //将该点入队尾
            }
        }
    }
    return dis[n-1][m-1];//dis[n-1][m-1]是指坐标为(n-1,m-1)的点距离坐标(0,0)的距离
}

int main()
{
    cin>>n>>m; //输入迷宫的尺寸大小
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<m;j++)
        {
            cin>>maze[i][j]; //输入迷宫,比如输入maze[1][1]=0,maze[1][2]=1
        }
    }

    cout<<bfs()<<endl; //输出宽度优先搜索结果
    return 0;
}

四、深度优先搜索之DFS

 

n皇后模板:

#include <iostream>
using namespace std;

const int N = 20;
int n;//棋盘有多少行
char g[N][N];
bool col[N], dg[N], udg[N];//一开始默认为false,即没被用过

void dfs(int row)//表示第row行皇后放在哪
{
    if (row == n)//0到n-1层共n层的棋盘已经排好了
    {
        for (int i = 0; i < n; i ++ ) puts(g[i]);
        puts("");
        return;//退出
    }

    for (int i = 0; i < n; i ++ )第row行的皇后可以放在第i列吗
        if (!col[i] && !dg[row + i] && !udg[n - row + i])
        {
            g[row][i] = 'Q';
            col[i] = dg[row + i] = udg[n - row + i] = true;//表示用过
            //col=true代表这一列都被标记用过
            //dg=true代表副对角线全被标记用过
            //udg=true代表主对角线全被标记用过
            dfs(row + 1);
            //回溯
            col[i] = dg[row + i] = udg[n - row + i] = false;
            g[row][i] = '.';
        }
}

int main()
{
    cin >> n;
    for (int i = 0; i <n; i ++ )
        for (int j = 0; j < n; j ++ )
            g[i][j] = '.';//一开始棋盘上面放'.'

    dfs(0);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/mabaizi/article/details/129992256
今日推荐