迷宮問題及延伸

2022-06-28 12:45:09 字數 3357 閱讀 9151

迷宮問題

問題描述:給定乙個m×n的迷宮圖,求所有從指定入口 到出口的路徑。假設迷宮圖如下圖所示(其中m=6,n=6,含 外圍加上一圈不可走的方塊,這樣做的目的是避免在查詢時 出界),迷宮由方塊構成,空白方塊表示可以走的通道,帶 陰影方塊表示不可走的障礙物。 要求所求路徑必須是簡單路徑,即在求得的路徑上不能 重複出現同一空白方塊,而且從每個方塊出發只能走向上下 左右四個相鄰的空白方塊。

用回溯法解決迷宮問題

回溯法=dfs+剪枝函式

回溯法實際上乙個類似窮舉的搜尋嘗試過程,主要是 在搜尋嘗試過程中按照深度優先的方法尋找問題的解,當 發現已不滿足求解條件時,就「回溯(backtracking)」 (即回退,走不通就掉頭),嘗試別的路徑。

回溯法在用來求問題的所有解(或最優解)時,要回 溯到根,且根結點的所有子樹都已被搜尋遍才結束。 • 而在求任一解(存在性問題)時,只要搜尋到乙個解 就結束。 • 這種以深度優先(dfs)的方式系統地搜尋問題的解的 演算法稱為回溯法,它適合於解一些組合數較大的問題。

在解決迷宮問題時,需要注意:1.結束  當起止點座標等於終點 2.走過的點一定要標記,否則會再回溯過去 3.設定乙個函式能控制點上下左右四個方向 4.採用回溯時一定要清理資料。恢復路徑(把走過的點恢復為0等)。

**//迷宮問題

#include

#include

#define row 10

#define col 10

int pathlen=0;

int path[row*col];

int maze[row][col] = ,

, //1

,, //3

,, //5

,, //7

,// 0 3 5 7 9

};void print_maze();

void print_path(int,int);

int make_new_place(int,int,int);

bool dfs(int,int,int,int);

int main(void)

printf("終點座標\n");

scanf("%d %d",&end_r,&end_c);

if(maze[end_r][end_c]!=0)

maze[start_r][start_c]=-2;

print_maze();

dfs(start_r,start_c,end_r,end_c);

return 0;

}void print_maze()

printf("\n");

}printf("\n");

return;

}void print_path(int start_r,int start_c)

return;

}int make_new_place(int place_r,int place_c,int director)

if(maze[new_r][new_c]==0)

ret_place=new_r*col+new_c;

if(maze[new_r][new_c]==-2)

ret_place=-2;

return ret_place;

}bool dfs(int start_r,int start_c,int end_r,int end_c)

int new_p;

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

}return result;

}騎士遍歷問題

即設定乙個棋盤,設定乙個起點,讓中國象棋中的馬遍歷整個棋盤。

我的做法是 當馬遍歷整個棋盤時因為不能重複走,則走的次數等於棋盤格仔數-1.

當達到這個條件輸出結果。

其他與迷宮問題類似

注意:可以跟迷宮問題一樣,設定乙個陣列,陣列大小與棋盤一樣,不初始化的話每個值為0,走過乙個點,將這個點設定乙個值。這樣使這個點不會再被走過。還可以走過乙個點後,將這個點標記,利用陣列標記為1,。兩種方法原理類似。馬有8種可能的方向,注意約束。

#include

#include

#include

#define n 20

int len;

int path_len=0;

int a_mark[n][n];

int solution=0;

int path[n*n];

void mark(int);

void unmark(int);

void print_path();

int make_new_place(int,int,int);

bool dfs(int,int);

int main(void)

bool dfs(int start_r,int start_c)

else}}

return result;

}int make_new_place(int start_r,int start_c,int i)

if(new_r>=0&&new_r=0&&new_c(%d %d)",s,j);

}printf("\n");

}延伸一下,若要求出兩點最短的路徑。

此時結束條件設定為起始點與終點相同。若要輸出最短路徑,意思是要保留上一次路徑的資料。我設定了乙個陣列保留每種解法所需要的步數。如果新的步數更小則將此時的最短路徑重新整理,若新的步數更大,則替換,使此時的步數最小。

#include

#include

#define n 51

#define m 1000

int len;

int pathlen=0;

int mark[n][n];

int path[n*n];

int best_path[n*n];

int m[m];

int solution=0;

bool dfs(int,int,int,int);

void print_path(int);

void print_best(int);

int make_new_place(int,int,int);

int main(void)

printf("\n");

return 0;

}bool dfs(int start_r,int start_c,int end_r,int end_c)

int i;

for(i=0;i<8;i++)

}return result;

}void print_path(int limit)

printf("\n");

if(solution==1)

return;

}void print_best(int limit)

裝箱問題及延伸

有乙個箱子容量為v 正整數,o v 20000 同時有n個物品 30 每個物品有乙個體積 o 正整數 10000 要求從 n 個物品中,任取若千個裝入箱內。方法1 設 f i 為不超過 i 的最大值,就可以看做揹包。即費用等於價值。得 f j max includeusing namespace s...

struct sockaddr定義及延伸

跟蹤看一下 strcut sockaddr 是怎麼定義的,這個定義在 usr include bits socket.h裡 引用 struct sockaddr 由上可見,sockaddr 結構體的第乙個成員是乙個巨集定義,再來看一下這個巨集定義 在 usr include bits sockadd...

從微控制器角度看堆疊及部分延伸問題

本文章為網路資源摘抄與總結,能力有限,有錯誤與漏洞希望大佬們給予提示或幫助,感謝 一 堆疊的相關概念 1 棧區 stack 由編譯器自動分配和釋放,存放函式的引數值 區域性變數的值等,其操作方式類似 於資料結構中的棧。2 堆區 heap 一般由程式設計師分配和釋放,若程式設計師不釋放,程式結束時可能...