算法设计与分析——分治与递归——整数划分问题
將正整數n表示為一系列正整數之和,
n=n1+n2+n3+n4+......+nk (其中,n1>=n2>=n3>=n4........>=nk>0,k>=1)正整數n的這種表示成為正整數n的劃分。正整數n的不同劃分個數成為正整數n的劃分數,記作p(n)。
例如,正整數6有如下11種劃分:
6;
5+1;
4+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;
其實這種問題可以認為是把n劃分為 加數小于或等于某個數的劃分,在這里把這個數成為m。例如,對6的劃分可以認作是將6劃分為加數小于等于6的劃分,因為6的加數確實小于等于6,為什么要引入這個m呢,是因為我們發現,從這個角度思考,比較容易求解。我們將劃分的種類數記為q(n,m)
在遞歸里,要對形參進行判斷
(1)當n=1時 q(1,m):表示是對1的劃分,那么只有一種劃分方式 1
(2)當m=1時q(n,1):當m=1時其實就是把讓所有加數小于等于1,那就是所有加數都是1咯(不考慮負數),當然也只有一種劃分方式
(3)當n==m時q(n,n):此時就是對n的劃分出來的數沒有限制,默認限制就是不大于n,此時劃分的總類數要分兩種情況才比較好解決:
1.劃分出來的數包含n(或m,因為n==m):那只有一種方式 比如 6的劃分 只有 6;一種方式2.劃分出來的數不包含n(或m,因為n==m):就可以認為是將6劃分出來的數都小于6,其實就是都小于或等于5,接下來 其實就是求出來q(n,n-1)或者是q(n,m-1),此時n>m-1,放到遞歸方程里就是求解q(n,m) n>m綜合起來 q(n,n)=1+q(n,m-1)(4)當n>m時:當遇到這個問題時,其實可以看做是對n的劃分有了條件,就是所有的劃分出來的數小于m,在上文中,6有11種劃分方式,那是沒有對6劃分出來的數進行限制,當要使劃分出來的數都小于某個數時比如5時,那就不是11種了。
5+1;
4+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;
這個時候分兩種情況:包含m和不包含m :
不包含m就是:
4+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;這些情況,其實就是求6的劃分出來的數小于等于4的情況,放到遞歸方程就是 q(n,m-1)
包含m就是:
5+1;
這個時候,確定這種劃分數量的時候m不再是主角,我們只要求出來n-m的劃分情況就行了,因為此時的m的劃分情況,取決于n-m。 比如包含m=5的劃分情況就是 6-5=1的情況,比如包含4的劃分情況就是求6-4=2,2的沒有限制的劃分情況。放到遞歸方程里面就是q(n-m,m)
(5)q(n,m)n<m:n<m時,比如n=6,m=7 求得就是6得劃分數小于等于7的情況,其實就是求解小于等于6,故此時情況就是求解q(n,n);
根據以上分析:
q( n, n ) = 1, 當 n ==1;
q( n, n ) = 1, 當m == 1;
q( n, n ) = q( n,n ) , 當n < m;
q( n, n ) = q( n, m-1) +1 , 當n == m;
q( n, n ) = q( n - m, m ) + q( n , m -1) , 當n > m>0;
#include<iostream> using namespace std; int q(int n,int m) {if((n<0)||(m<0))return 0;if((n==1)||(m==1))return 1;if(n<m)return q(n,n);if(n==m)return (1+q(n,m-1));if(1<m<n)return q(n,m-1)+q(n-m,m); } int main() {int n;cout<<"輸入需要來解決的整數劃分問題的數字:"<<endl;cin>>n; cout<<n<<"的整數劃分的個數一共有"<<q(n,n);return 0;}總結
以上是生活随笔為你收集整理的算法设计与分析——分治与递归——整数划分问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何使用exclipse打开已有的文件夹
- 下一篇: 算法设计与分析——分支限界法——装载问题