一、图论,最短路径问题之朴素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;
}