深搜入门DFS
1、什么是深搜?
? ? ? ? 深度優先搜索屬于圖算法的一種,英文縮寫為DFS,即 Depth First Search。其過程簡要來說是對每一個可能的分支路徑深入到不能再深入為止,而且每個節點只能訪問一次。
? ? ? ? 舉例說明之:下圖是一個無向圖,如果我們從A點發起深度優先搜索(以下的訪問次序并不是唯一的,第二個點既可以是B也可以是C,D),則我們可能得到如下的一個訪問過程:A->B->E(沒有路了,回溯到A),A->C->F->H->G->D(沒有路,最終回溯到A,A也沒有未訪問的相鄰節點,本次搜索結束)。
2、深搜框架
void backtrack(int t)
{
? ? ? ? if ( t>n) ? ? ?// t:遞歸深度,即當前擴展結點在解空間樹中的深度,t>n,搜索至葉子結點
? ? ? ? ? ? output(x) ?// 記錄或輸出可行解
? ? ? ? else
? ? ? ? ? ? for i=start to end ? // strat,end,當前擴展點處未搜索過的子樹的起始編號和終止編號
? ? ? ? ? ? {
? ? ? ? ? ? ? ? x[t]=h(i) ? ? ? // h(i):當前擴展點處x[t]的第 i 個可選值
? ? ? ? ? ? ? ? if (當前擴展結點的約束條件)
? ? ? ? ? ? ? ? ? ? backtrack(t+1)
? ? ? ? ? ? }
}
3、從枚舉到深搜
? ? ? ? 一個三位數abc,如果滿足abc = a^3+ b^3+ c^3,那么就把這個數叫做水仙花數。如果一個N位數所有數碼的N次方的和加起來等于這個數字本身,我們把這樣的數叫做廣義水仙花數,現在,我們的任務是,輸入一個m (m<7),讓你求出所有滿足N = m的廣義水仙花數。
樣例輸入1:3? ? ? ? ? 樣例輸出2:153 370 371 407
樣例輸入2:5? ? ? ? ? 樣例輸出:54748 92727 93084
分析:
? ? ? ? 如果是水仙花問題,可以用枚舉,直接求出。代碼如下:
#include <stdio.h> int main() {int i,a,b,c;for(i=100;i<=999;i++){a=i/100;b=i/10%10;c=i%10;if(a*a*a+b*b*b+c*c*c==i)printf("%d ",i);}printf("\n");return 0; }或:
#include <stdio.h> int main() {int a,b,c;for(a=1;a<=9;a++)for(b=0;b<=9;b++)for(c=0;c<=9;c++)if(a*a*a+b*b*b+c*c*c==a*100+b*10+c)printf("%d%d%d ",a,b,c);printf("\n");return 0; }? ? ? ? 現在求廣義的水仙花,現在的難點是不知道是幾位數?也不知道是幾次方?循環層數不確定,那么該如何實現m重循環?答案只有一個:就是遞歸,讓系統自動調用函數,自動實現循環。
? ? ? ? 套用上面深搜(回溯)模板,代碼自然而成。
#include <stdio.h> #include <math.h> int n; void flower(int t,int curNum,int curSum) {int i,start;if(t>n){if(curNum==curSum)printf("%d ",curNum);}else{start=(t==1); // 第一位不為0,第一位1~9枚舉,其他位0~9枚舉 for(i=start;i<=9;i++)flower(t+1,curNum*10+i,curSum+(int)pow(i,n));// 縮小問題規模} } int main() {while(scanf("%d",&n) && n){flower(1,0,0);printf("\n");}return 0; }?
總結
- 上一篇: 信息学奥赛一本通(1115:直方图)
- 下一篇: 信息学奥赛一本通 2057:【例3.9