小谈深度优先搜索
最近讀了一本算法書,書中提到了深度優先算法,于是我就整理了一下。
 
引入小題:
 
解決方案:這里先使用最簡單最常用的窮舉法時行求解。(此代碼中的book數組起到了標記的作用,可以參考桶裝法排序了解標記的好處和作用)
#include <stdio.h>int main(){//因為要填寫9個數字,所以這里用數組a存放9次數字的變量,方便在book標記數組內操作 int a[10], book[10];int i, sum, total = 0;for(a[1] = 1; a[1] <= 9; a[1] ++)for(a[2] = 1; a[2] <= 9; a[2] ++)for(a[3] = 1; a[3] <= 9; a[3] ++)for(a[4] = 1; a[4] <= 9; a[4] ++)for(a[5] = 1; a[5] <= 9; a[5] ++)for(a[6] = 1; a[6] <= 9; a[6] ++)for(a[7] = 1; a[7] <= 9; a[7] ++)for(a[8] = 1; a[8] <= 9; a[8] ++)for(a[9] = 1; a[9] <= 9; a[9] ++){//初始book標記數組 for(i = 1; i <= 9; i++){book[i] = 0;}//將獲得的序列標記一下,方便判斷是否全為不一樣的數字for(i = 1; i <= 9; i++) {book[a[i]] = 1;}//用于判斷是否為9個不同的數字 sum = 0;for(i = 1; i <= 9; i++){if(book[i] == 1) sum ++;}if(sum == 9 && a[1] * 100 + a[2] * 10 + a[3] + a[4] * 100 + a[5] * 10 + a[6] == a[7] * 100 + a[8] * 10 + a[9] ){total ++;printf("%d%d%d + %d%d%d = %d%d%d\n", a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9]);}}printf("共有%d個這樣的數\n", total / 2); return 0; }
初入DFS小題:
給出n,組成n位的全排序。(1 <= n)
解決方案:如果已知n的話,可以在程序里面寫入n個for循環,來得出需要的結果,但是這個n是在程序運行時給出的,所以這里需要用遞歸實現。
 
#include <stdio.h> #include <stdlib.h>int *box, *book, n;void dfs(int step){int i;if(step >= n + 1){for( i = 1; i <= n; i++ ){printf("%d", box[i]); }printf("\n");return;}for(i = 1; i <= n; i++){if(book[i] == 0){box[step] = i;book[i] = 1;dfs(step + 1);book[i] = 0;}} }int main(){ int i;scanf("%d", &n);//因為此處下標要從1開始,所以數組要加1 box = (int *)malloc(sizeof(int) * (n + 1));book = (int *)malloc(sizeof(int) * (n + 1));//初始book標記數組for(i = 1; i <= n; i++) book[i] = 0;dfs(1);return 0; }
涉及算法:可以把DFS歸結為如下模型
void dfs(int step) {判斷邊界 (越界返回) 嘗試每一種可能 for(i = 0; i < n; i++) {處理繼續下一步 dfs(step + 1) 處理 } }
重試第一題: 可使用DFS算法來編寫這個題,運行效率能提高10倍(當然,這個算法效率也不高)。
#include <stdio.h> #include <stdlib.h>int *box, *book, n = 9, total = 0;void dfs(int step){int i;if(step >= n){if(box[0] * 100 + box[1] * 10 + box[2] +box[3] * 100 + box[4] * 10 + box[5] ==box[6] * 100 + box[7] * 10 + box[8]){total ++;printf("%d%d%d + %d%d%d = %d%d%d\n", box[0], box[1], box[2], box[3], box[4], box[5], box[6], box[7], box[8]);}return;}for(i = 1; i <= n; i++){if(book[i-1] == 0){box[step] = i;book[i-1] = 1;dfs(step + 1);book[i-1] = 0;}} }int main(){ int i;scanf("%d", &n);//因為此處下標要從1開始,所以數組要加1 box = (int *)malloc(sizeof(int) * (n));book = (int *)malloc(sizeof(int) * (n));//初始book標記數組for(i = 0; i < n; i++) book[i] = 0;dfs(0);printf("共有%d個", total / 2); return 0; }
再來一題:
有一天,小哈一個去玩迷宮。但是方向感很不好的小哈很快就迷路了。小哼得知后便立即去解救無助的小哈。小哼當然是有備而來,已經弄清楚了迷宮地圖,現在小哼要以最快速度去解救小哈。問題就此開始了……
   迷宮由n行m列的單元格組成,每個單元格要么是空地,要么是障礙物。你的任務是幫助小哼找到一條從迷宮的起點到小哈所在位置的最短路徑,注意障礙物是不能走的,當然也不能走到迷宮之外。n和m都小于等于100。
 
 
輸入格式:第一行有兩個數N M。N表示迷宮的行,M表示迷宮的列。接來下來N行M列為迷宮,0表示空地,1表示障礙物。最后一行4個數,前兩個數為迷宮入口的x和y坐標。后兩個為小哈的x和y坐標。
樣例:
#include <stdio.h> #include <stdlib.h> #include <string.h>int **map, **book, min = 999999; int p, q, M, N; //終點 void dfs(int x, int y, int step){int i, cX, cY;//方向數組int next[4][2] = {{0, 1}, //右 {1, 0}, //下 {0, -1}, //左 {-1, 0} //上};//邊界條件 if( x == p && y == q) {if(step < min) min = step;return;}//遍歷條件(四個方向)for(i = 0; i < 4; i++){cX = x + next[i][0];cY = y + next[i][1];//越界 不操作 if(cX < 0 || cY < 0 || cX > N - 1 || cY > M - 1) continue;if(book[cX][cY] == 0 && map[cX][cY] == 0){//標記此地點已走過 book[cX][cY] = 1;dfs(cX, cY, step + 1);book[cX][cY] = 0; } }return; }int main(){ int startX, startY;int i, j;scanf("%d %d", &N, &M); map = (int **)malloc(sizeof(int *) * N);book = (int **)malloc(sizeof(int *) * N);for(i = 0; i < N; i++){map[i] = (int *)malloc(sizeof(int) * M);book[i] = (int *)malloc(sizeof(int) * M);}for(i = 0; i < N; i++)for(j = 0; j < M; j++)book[i][j] = 0;for(i = 0; i < N; i++){for(j = 0; j < M; j++){scanf("%d", &map[i][j]);}} scanf("%d %d %d %d", &startX, &startY, &p, &q);startX--;startY--;p--;q--;book[startX][startY] = 1;dfs(startX, startY, 0);if(min == 999999){printf("No Way!");}else{printf("%d", min); }return 0; }可見此算法效率并不高。
 
BFS算法處理(明顯提高時間復雜度,但空間復雜度提升):
#include <stdio.h>struct Node{int x;int y;int s; };int main(){int startX, startY, n, m, p, q, tX, tY, head = 1, tail = 1, flag = 0;int i, j;int a[101][101] = {0}, book[101][101] = {0},next[4][2]={{0, 1}, //右 {1, 0}, //下 {0, -1}, //左 {-1, 0} //上 };struct Node que[100000];//接收初值 scanf("%d %d", &n, &m);for(i = 1; i <= n; i++){for(j = 1; j <= m; j++){scanf("%d", &a[i][j]);}}scanf("%d %d %d %d", &startX, &startY, &p, &q);que[tail].x = startX;que[tail].y = startY;que[tail].s = 0;book[startX][startY] = 1;tail ++;while(head < tail){for(i = 0; i < 4; i ++){tX = que[head].x + next[i][0];tY = que[head].y + next[i][1];if(tX < 1 || tX > n || tY < 1 || tY > m){continue;}if(a[tX][tY] == 0 && book[tX][tY] == 0){que[tail].x = tX;que[tail].y = tY;que[tail].s = que[head].s + 1;book[tX][tY] = 1;tail ++;if(tX == p && tY == q){flag = 1;}}}if(flag == 1) break;head ++;}if(flag == 1){printf("%d", que[tail - 1].s);}else{printf("No Way!");}return 0; }
博客名稱:王樂平博客
博客地址:http://blog.lepingde.com
CSDN博客地址:http://blog.csdn.net/lecepin
總結
                            
                        - 上一篇: ADC的DMA多通道数据采集(雨滴传感器
 - 下一篇: VB中使用GDI+进行图像缩放的实例