前幾天在演算法書上看到乙個整數拆分的題目,覺得挺有意思,記錄如下:
例如:n==6有 6
5+14+2 4+1+1
3+3 3+2+1 3+1+1+1
2+2+2 2+2+1+1 2+1+1+1+1
1+1+1+1+1+1
共11種分解方法,所以輸出應該為11。
拆分按照因子從大到小排列,每一次拆分都可視為問題規模的減少,所以可以使用遞迴解決。
設q(n,m)為整數n使用不大於m的整數進行拆分的所有情況總數,因此有
1)當n==m時
可以分為兩種情況,乙個是使用n本身,只有一種情況。二個是使用不大於n-1的整數進行拆分。
所以此時q(n,m)=1+q(n,n-1);
2)當n
使用比n大的數進行拆分沒有意義,所以此時q(n,m)=q(n,n)
3)當n>m時
這時候有兩種情況,乙個是使用m對n進行拆分,乙個是使用小於m的數對n進行拆分
對於第乙個,使用m對n進行拆分,所以拆分出來的情況最大的數是m,剩下的所有數加起來為n-m,問題變成使用不大於m的整數對n-m進行拆分,所以此時為q(n-m,m)
對於第二個,使用小於m的數對n進行拆分,表示為q(n,m-1)
4)當n==1或者m==1時 只有一種情況,返回1。注意,這裡可能會漏掉m==1的情況,實際上這種情況是存在的。
所以可以使用遞迴函式程式設計如下:
#include #include using namespace std;
int q(int n,int m)
if(nm)
return q(n,m-1)+q(n-m,m);
}void main()
}
使用母函式法
整數分解用母函式可以這樣理解,分別用任意個1,2,3,4,……,n可以加起來可以表示成n的種數。又因為當使用整數m對n進行分解時,所使用的次數不能多於n/m次,所以可以寫下母函式如下:
g(x)=(1+x^1+x^2+……+x^n)*(1+x^2+x^4+……+x^((n/2)*2))*……
*(1+x^m+x^(2*m)+x^(3*m)+……+x^((n/m)*m))*……*(1+x^n)
在程式中使用set陣列表示每一輪乘法後得到係數,c陣列表示到現在為止乘法得到的係數總和。最後算出結果後x^n對應的係數則為可分解的可能數。**如下:
#includeconst int num=1000;
int set[num];
int c[num];
void init()
if(n==1)
else if(m==1){
//當m為1,意味著要輸出n個m相加
for(int i=0; im){
//如果n大於m,使用m作為分解,則要首先輸出m+的形式
printf("%d+",m);
//記錄下作為樹幹節點m的值並使i自增
set[i++]=m;
//遞迴輸出m+以後的分解
q(n-m,m,i);
//遞迴完畢後需要將陣列記錄後退乙個,回到上乙個節點,如上圖示過程2
i--;
//執行另乙個分支,在下一次遞迴之前輸出記錄的資料,如上圖示過程3
for(int j=0; j
整數拆分的兩種解法(已完成)
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!分類 演算法 2012 09 30 17 04 263人閱讀收藏 舉報目錄 題目 給定乙個整數n,輸出這個整數拆分的可能總數 分析一分析二 題目二 給定乙個整數n,輸出這個整數拆分的可能形式 即輸出全部情況 前幾天在演算法書上看到乙個整數拆分的題目...
nyoj90 整數拆分(遞迴,揹包兩種解法)
題目 把乙個整數拆分成的所有情況。遞迴 include includeusing namespace std int z 11 int zh int n,int m 最近在做動態規劃的時候發現這個題目也可以用揹包來些,並且比用遞迴喜惡簡單的多。效率也高很多。動態轉移方程 dp i dp i dp i...
Bacon Number 兩種解法
view code 題目 cid 567 題目分析 與longth way 類似 這個好象就是傳說中的六度人脈,你只要通過六度人脈就可以找到世界上的任何乙個人。假設乙個人一生會認識n個人,那n n 1 n 2 n 3 n 4 n 5 n 6 世界總人數。給定一些邊確定乙個圖,即給定一些點之間的連通情...