總結剛剛大一,第一篇記錄如下?
這道題題目理解很簡單,自然數拆分,但要是用單純迴圈卻很難解決。因此我們想到dfs深搜(深度優先搜尋)進行解題。這道題是一道很典型的dfs入門題型,由此可以引發許多變式。 簡介
深度優先搜尋演算法(depth first search,簡稱dfs):一種用於遍歷或搜尋樹或圖的演算法。 沿著樹的深度遍歷樹的節點,盡可能深的搜尋樹的分支。當節點v的所在邊都己被探尋過或者在搜尋時結點不滿足條件,搜尋將回溯到發現節點v的那條邊的起始節點。整個程序反覆進行直到所有節點都被訪問為止。屬於盲目搜尋,最糟糕的情況演算法時間複雜度為o(!n)。
這麼多不如一張圖:
我的dfs模版(深搜回溯)
search(i)}}
執行截圖#include
int a[
100]
;int n;
void
(int j)
//輸出資料
printf
("\n");
}void
search
(int sum,int j ,int s)
//dfs深搜
a[j]
=i;search
(sum,j+
1,i)
; sum-=i;
//回溯}}
int main()
return0;
}
我們這題中運用回溯的技巧,即sum -= i,在搜尋中,不要過多注意細枝末節,巨集觀分析函式總體功能。
什麼在控制公升序?
我們可以從 for(int i=s;i<=n;i++) 看出,我們在「播撒」運算元的時候,起始時在控制是否公升序,倘若我用
for(int i=1;i<=n;i++)即不要s變數 ,這樣的結果為
我們可以畫圖理解。
此結果為#include
int book[
100]
;int a[
100]
;int n;
void
(int j
)printf
("\n");
}void
search
(int sum,int j,int s
) a[j]
=i; book[i]=1
;search
(sum,j+
1,i)
; book[i]=0
; sum-=i;}}
int main()
return0;
}
在這裡,我們又更進一步運用回溯的作用,用book【】建立判斷陣列來判斷每個數是否取過,若取過,則在此記錄陣列a【】處標1,直到最後走到枝節末端向上時return一級回溯為0一次,以此類推,即可知數是否取過。
在此題中不僅運用深搜,而且還有回溯的小技巧,對於像我一樣的新手是乙個很好的練習。
望多多指教
洛谷 P2404 自然數的拆分問題
任何乙個大於1的自然數n,總可以拆分成若干個小於n的自然數之和。任何乙個大於1的自然數n,總可以拆分成若干個小於n的自然數之和。輸入格式 輸入 待拆分的自然數n。輸出格式 輸出 若干數的加法式子。輸入樣例 1 複製 7 輸出樣例 1 複製 1 1 1 1 1 1 1 1 1 1 1 1 2 1 1 ...
洛谷 P2404 自然數的拆分問題
任何乙個大於1的自然數n,總可以拆分成若干個小於n的自然數之和。任何乙個大於1的自然數n,總可以拆分成若干個小於n的自然數之和。輸入格式 輸入 待拆分的自然數n。輸出格式 輸出 若干數的加法式子。輸入樣例 1 複製7 輸出樣例 1 複製1 1 1 1 1 1 1 1 1 1 1 1 2 1 1 1 ...
洛谷 P2404 自然數的拆分問題
任何乙個大於1的自然數n,總可以拆分成若干個小於n的自然數之和。現在給你乙個自然數n,要求你求出n的拆分成一些數字的和。每個拆分後的序列中的數字從小到大排序。然後你需要輸出這些序列,其中字典序小的序列需要優先輸出。輸入 待拆分的自然數n。輸出 若干數的加法式子。輸入 17輸出 11 1 1 1 1 ...