洛谷 P2404 自然數的拆分問題C語言

2021-10-22 03:51:16 字數 1741 閱讀 9391

總結剛剛大一,第一篇記錄如下?

這道題題目理解很簡單,自然數拆分,但要是用單純迴圈卻很難解決。因此我們想到dfs深搜(深度優先搜尋)進行解題。這道題是一道很典型的dfs入門題型,由此可以引發許多變式。 簡介

深度優先搜尋演算法(depth first search,簡稱dfs):一種用於遍歷或搜尋樹或圖的演算法。 沿著樹的深度遍歷樹的節點,盡可能深的搜尋樹的分支。當節點v的所在邊都己被探尋過或者在搜尋時結點不滿足條件,搜尋將回溯到發現節點v的那條邊的起始節點。整個程序反覆進行直到所有節點都被訪問為止。屬於盲目搜尋,最糟糕的情況演算法時間複雜度為o(!n)。

這麼多不如一張圖:

我的dfs模版(深搜回溯)

search(i)}}

#include

int a[

100]

;int n;

void

print

(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

print

(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 ...