迷宫搜索问题最短路_【算法常用模板】总结(更新中)
搜索類
圖類
排序類
并查集
數學類
位運算
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);
}
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的迷宫搜索问题最短路_【算法常用模板】总结(更新中)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 包概念与__init__注意事项
- 下一篇: 数据结构中的队列