2019 7 25 搜尋練習一 自然數的拆分

2021-09-25 14:02:09 字數 1461 閱讀 9905

洛谷p2404 自然數的拆分 2019.7.25

題目描述

任何乙個大於1的自然數n,總可以拆分成若干個小於n的自然數之和。現在給你乙個自然數n,要求你求出n的拆分成一些數字的和。每個拆分後的序列中的數字從小到大排序。然後你需要輸出這些序列,其中字典序小的序列需要優先輸出。

輸入格式

輸入:待拆分的自然數n。

輸出格式

輸出:若干數的加法式子,方案總數。

輸入輸出樣例

輸入 #1 複製

7輸出 #1 複製

7=1+1+1+1+1+1+1

7=1+1+1+1+1+2

7=1+1+1+1+3

7=1+1+1+2+2

7=1+1+1+4

7=1+1+2+3

7=1+1+5

7=1+2+2+2

7=1+2+4

7=1+3+3

7=1+6

7=2+2+3

7=2+5

7=3+4

total=14

審題:1.按字典序排列,後面新增的數始終大於等於前乙個數字。

2.sum=n

演算法及思路:

1.既然可以從小找到大,考慮用深,遍歷所有小於n的數+記憶化搜尋來做

2.dfs函式的設定,考慮當前狀態:

比如待拆分的數字為num,可以考慮減去從i到num-1的所有數,這個地方可以考慮用迴圈來找減數,同時注意到減數受到來自前一步的減數的限制,這一步的數必須大於等於前一步的數,設該減數為t。那麼此時num=num-t,問題轉化為拆分num-t,可以用遞迴實現。

3.從上方的描述中可以看出,dfs函式需要維護至少兩個引數:當前正在拆分的數以及當前拆分的次數。前者容易明白,後者呢??因為受到來自前乙個減數的限制,可以考慮用乙個陣列a來記錄每一步的減數,那麼要求i>=a[step-1]即可!!!同時,由於記錄了每一步的減數,那麼最後當num==0時列印拆分數序列的問題也就迎刃而解了(只需要遍歷從a陣列1到step的所有元素即可)。同時,保留了前一種拆分方法的主體,當dfs函式返回上層棧時,只需要更改最後的幾個數就行了,不必重新遍歷前方的選擇值。

元素解釋:

dfs(int num,int step) 申明dfs維護的兩個狀態:當前正在拆分的數,和已拆分次數

a[maxn] 每一步拆分改變的數

print() 用來列印各種拆分序列

total 計數器,用來記錄拆分的方法數

#include//cin、cout標頭檔案

#define maxn 100100 //巨集定義maxn

using namespace std;

int n,total; //給出待拆分數n,拆分方法total

int a[maxn]=; //因為每一步所拆分的資料至少為1,故初始化為1.

void print(int x)//列印函式,x儲存當前的拆分方法所需要的拆分次數

自然數拆分

描述 description 輸入自然數n,然後將其拆分成由若干數相加的形式,參與加法運算的數可以重複。輸入格式 inputformat 輸入只有乙個整數n,表示待拆分的自然數n。n 80 輸出格式 outputformat 輸出乙個數,即所有方案數 樣例輸入 sampleinput 複製資料 7 ...

自然數拆分

問題描述 自然數的拆分 任何乙個大於1的自然數n,總可以拆分成若干個自然數之和,並且有多種拆分方法。試求 n的所有拆分。例如自然數5,可以有如下一些拆分方法 5 1 1 1 1 1 5 1 1 1 2 5 1 2 2 5 1 4 5 2 3 注意,本題中n拆分出來的數x的範圍是1 x整數劃分可以參考...

自然數拆分

題目 給出sum min max和n四個正整數,請輸出所有將sum拆分為n個遞增的正整數 允許相等 之和,其中每個正整數k都滿足 min k max。在少俠的部落格 看到這道題 就隨手做了下。該題與輸出n個數取m個數的所有組合類似,只不過限定了m個數的和以及取值範圍。可以先用貪心演算法構造乙個最小的...