整數拆分的兩種解法(已完成)

2021-08-31 16:18:42 字數 2366 閱讀 2418

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!

分類: 演算法

2012-09-30 17:04

263人閱讀收藏 

舉報目錄(?)

[-] 題目:給定乙個整數n,輸出這個整數拆分的可能總數

分析一分析二

題目二:給定乙個整數n,輸出這個整數拆分的可能形式(即輸出全部情況)

前幾天在演算法書上看到乙個整數拆分的題目,覺得挺有意思,記錄如下:

例如:n==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的情況,實際上這種情況是存在的。

所以可以使用遞迴函式程式設計如下:

[cpp]view plain

copy

#include 

#include 

using

namespace std;  

int q(int n,int m)  

if(nreturn q(n,n);  

if(n==m)  

if(n>m)  

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對應的係數則為可分解的可能數。**如下:

[cpp]view plain

copy

#include

const

int num=1000;  

int set[num];  

int c[num];  

void init()  

}  int main()  

}  for(int x=0; x<=n; x++)  

}  printf("%d\n",c[n]);  

}  return 0;  

}  

使用遞迴情況(輸出實在麻煩。。弄了很久(>﹏

整個輸出類似於一顆樹,以分解6為例,過程如下圖

**如下:

[cpp]view plain

copy

#include 

//使用乙個陣列記錄在遞迴過程中產生的前面需要重複輸出的值

int set[100];  

//用於在遞迴過程中判斷是否遞迴到最深處,輸出回車

int k;  

//此函式表示使用不大於m的整數對n進行拆分的情況,i用於表示set陣列已經存在的記錄數長度

void q(int n,int m,int i)  

if(n==1)  

else

if(m==1)  

if(nq(n,n,i);  

}  if(n==m)  

if(n>m)  

}  void main()  

整數拆分的兩種解法(已完成)

前幾天在演算法書上看到乙個整數拆分的題目,覺得挺有意思,記錄如下 例如 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。拆分按照因子從大到小排列,每一次拆分都可視...

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 世界總人數。給定一些邊確定乙個圖,即給定一些點之間的連通情...