迷宫搜索问题最短路_【算法常用模板】总结(更新中)

搜索类

图类

排序类

并查集

数学类

位运算

Part1 搜索类

bfs 求迷宫问题最短路径(未验证)

#include

#include

using namespace std;

//用于遍历的结构 (可以添加题目所要求的信息)

typedef struct Node{

int x,y;

int step;

}NODE;

const int NUM = 100; //地图最大范围,根据要求具体修改

int M,N;

int m[NUM][NUM]; // 地图数组

int vis[NUM][NUM];

bool check(NODE& node){

int x = node.x;

int y = node.y;

//三种不可访问情况

if(x < 1 || y < 1 || x > M || y > N ) return 0; //地图边界判断(一定要最先判断)

if(vis[x][y]) return 0; //是否被访问过判断

if(m[x][y] == '*') return 0; //是否是不可访问的节点判断(具体题目不同 假设为*)

//可访问

return 1;

}

//判断是否是所求的节点

bool checkRight(NODE& node){

if(m[node.x][node.y] == '1') return 1; //假设1为目标

return 0;

}

int mov[4][2]={{0,1},{0,-1},

{1,0},{-1,0}}; //用于移动的数组,这里是四个方向(具体问题具体分析)

NODE bfs(NODE startNode){

//初始化

queue Q;

vis[startNode.x][startNode.y] = 1;

Q.push(startNode);

//正式开始遍历

while(!Q.empty()){

NODE nowNode = Q.front(); //获取判断节点

if(checkRight(nowNode)) return nowNode; //达到目标节点,获取目标节点

//进行四个方向遍历(具体问题可能会不同)

for(int i = 0; i < 4; i++){

NODE nextNode;

//下一个位置信息

nextNode.step = nowNode.step + 1;

nextNode.x = nowNode.x + mov[i][0];

nextNode.y = nowNode.y + mov[i][1];

if(check(nextNode)){ //判断是否可访问;

vis[nextNode.x][nextNode.y] = 1; //标记为已访问

Q.push(nextNode);

}

}

}

}

int main(){

cin >> M >> N;

for(int i = 1; i <= M; i++)

for(int j = 1; j <= N; j++)

cin >> m[i][j];

//初始节点(根据题目具体要求位置)

NODE sNode;

sNode.step = 0;

sNode.x = 1;

sNode.y = 1;

NODE targetNode = bfs(sNode);

cout << targetNode.step << endl; //输出题目要的节点信息

}

dfs

求总的路径数目

Part2 图类

最小生成树 (Prim)

#include

using namespace std;

const int INF = 0x3fffffff;

int vis[N];

void prim(int c[][],int u) {

int i,j;

vis[u] = 1;

for(i = 1; i <= N; i++) {

closet[i] = c[u][i];

}

for(i = 0; i < N; i++){

int t = u;

int min = INF;

int j;

for(j = 1; j <= N; j++){

if(!vis[u] && lowcost[j] < min){

min = closet[j];

t = j;

}

}

if (t == u) break;

for(j = 1; j <= N; j++){

if(!vis[j] && lowcost[j]>c[t][j]){

lowcost[j] = c[t][j];

}

}

}

}

单元最短路 (DJ)

const int MAXINT = 32767;

const int MAXNUM = 10;

int dist[MAXNUM];

int prev[MAXNUM];

int A[MAXUNM][MAXNUM];

void Dijkstra(int v0)

{

bool S[MAXNUM]; // 判断是否已存入该点到S集合中

int n=MAXNUM;

for(int i=1; i<=n; ++i)

{

dist[i] = A[v0][i];

S[i] = false; // 初始都未用过该点

if(dist[i] == MAXINT)

prev[i] = -1;

else

prev[i] = v0;

}

dist[v0] = 0;

S[v0] = true;

for(int i=2; i<=n; i++)

{

int mindist = MAXINT;

int u = v0;    // 找出当前未使用的点j的dist[j]最小值

for(int j=1; j<=n; ++j)

if((!S[j]) && dist[j]

{

u = j; // u保存当前邻接点中距离最小的点的号码

mindist = dist[j];

}

S[u] = true;

for(int j=1; j<=n; j++)

if((!S[j]) && A[u][j]

{

if(dist[u] + A[u][j] < dist[j]) //在通过新加入的u点路径找到离v0点更短的路径

{

dist[j] = dist[u] + A[u][j]; //更新dist

prev[j] = u; //记录前驱顶点

}

}

}

}

多源最短路 (Floyd)

typedef struct

{

char vertex[VertexNum]; //顶点表

int edges[VertexNum][VertexNum]; //邻接矩阵,可看做边表

int n,e; //图中当前的顶点数和边数

}MGraph;

void Floyd(MGraph g)

{

int A[MAXV][MAXV];

int path[MAXV][MAXV];

int i,j,k,n=g.n;

for(i=0;i

for(j=0;j

{

A[i][j]=g.edges[i][j];

path[i][j]=-1;

}

for(k=0;k

{

for(i=0;i

for(j=0;j

if(A[i][j]>(A[i][k]+A[k][j]))

{   A[i][j]=A[i][k]+A[k][j];

path[i][j]=k;

}

} }

Part3 排序类

数组排序 sort

可对任意类型的数组排序。可以自定义排序规则

#include //头文件

sort(数组名,数组名+数组长度) //自定义排序

sort(数组名,数组名+数组长度,cmp比较规则) //自定义排序

//自定义排序规则

bool cmp(Node& a , Node& b){

if(a.x == b.x) return a.y < b.y;

return a.x < b.x;

}

cmp排序函数的自定义方法:

return true 就是a在b前

return false 就是b在a前

默认排序例子(小到大)

#include

#include

using namespace std;

const int N = 5;

int main(){

int arr[N];

for(int i = 0; i < 5; i++){

cin >> arr[i];

}

sort(arr, arr + N);

for(int i = 0; i < 5; i++){

cout << arr[i] <

}

return 0;

}

自定义排序例子

#include

#include

using namespace std;

typedef struct NODE{

int x,y;

}Node;

//自定义排序规则

bool cmp(Node& a , Node& b){

if(a.x == b.x) return a.y < b.y;

return a.x < b.x;

}

const int N = 5;

int main(){

Node arr[N];

for(int i = 0; i < 5; i++){

cin >> arr[i].x >> arr[i].y;

}

sort(arr, arr + N, cmp); //自定义排序

for(int i = 0; i < 5; i++){

cout << arr[i].x << " " <

}

return 0;

}

优先队列 priority_queue

用于动态排序的结构(需要不断的改变排序的元素)

如:哈夫曼树的构造

#include

priotrity_queue pq //默认定义 从大到小

priotrity_queue,cmp > pq

//自定义排序规则 (有两种不用自己写的规则less和greater less和默认一样从大到小 greater从小到大)

struct cmp {

bool operator() (Node& a , Node& b) {

if (a.x == b.x) return a.y < b.y;

return a.x < b.x;

}

};

//基本方法

pq.push(node) //加入队列

pq.empty() //队列是否

pq.top() //获得队头元素(注意和queue的区别,queue是front)

pq.pop() //出队

注意:true false 对应的方向刚好与sort相反

初步使用

#include

#include

#include

#include

using namespace std;

const int N = 5;

int main(){

priority_queue, greater > pq; //整型从小到大

// priority_queue, less > pq; //整型从大到小 同priority_queue pq;

int x;

for(int i = 0; i < 5; i++){

cin >> x;

pq.push(x);

}

while(!pq.empty()){

cout << pq.top() <

pq.pop();

}

return 0;

}

自定义排序例子

#include

#include

#include

#include

#define Node ElemType

using namespace std;

const int N = 5;

typedef struct NODE{

int x,y;

}Node;

//自定义排序规则

struct cmp {

bool operator() (Node& a , Node& b) {

if (a.x == b.x) return a.y < b.y;

return a.x < b.x;

}

};

int main(){

Node arr[N];

priority_queue, cmp> pq;

for(int i = 0; i < 5; i++){

cin >> arr[i].x >> arr[i].y;

pq.push(arr[i]);

}

while(!pq.empty()){

cout << pq.top().x << " " << pq.top().y <

pq.pop();

}

return 0;

}

Part4 并查集

初始化数组为-1

find(int a); //找老大

union(int a, int b) // a集团加入b集团

不带路径压缩:

int find(int a){

return boss[a]?find(a):a;

}

void union(int a, int b){

int fa = find(a);

int fb = find(b);

boss[a] = b;

}

带路径压缩:

int find(int a){

int bigBoss;

int son = a;

int temp;

while(boss[a]) a = boss[a];

bigBoss = a; //找到大老板

//把路径上的上司不是大老板的全部直属大老板

while( son != bigBoss ){

temp = boss[son];

boss[son] = bigBoss;

son = temp;

}

return bigBoss;

}

void union(int a, int b){

int fa = find(a);

int fb = find(b);

boss[a] = b;

}

Part5 数学类

最大公因数(辗转相除法)

int gcd(int a, int b){

return b>0?gcd(b,a%b):a;

}

最小公倍数

int gcd(int a, int b){

return b>0?gcd(b,a%b):a;

}

int lcm(int a, int b){

return a*b/gcd(a,b);

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值