我们用递归+记忆化的方法来解决普通整数划分问题:定义 f(n,m)为将整数n划分为一系列整数之和,其中加数
最大不超过m。
得到下面的递推关系式:
当n==1 || m==1 只有一种划分,即 1 或者 1+1+1......+1
当m>n 显然,等价于 f(n,n)
当m==n 此时:我考虑加数包含m与否的两种情况:
1)划分不包含m,即f(n,m-1)---所有m-1的划分
2)划分包含 m,此时只有一种即 m
所以当m==n时,有 f(n,m)=f(n,m-1)+1
当m<n时,
1)包含m时,{m,x1,x2,x3....xi}此时 等价于 f(n-m,m)
2)不包含m时,显然f(n,m-1)
所以f(n,m)=f(n,m-1)+f(n-m,m)
采用记忆化技术优化复杂度:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 using namespace std; 5 #define MAXN 130 6 int num[MAXN][MAXN]; 7 int dp(int n,int k) 8 { 9 if(n==1||k==1) 10 return 1; 11 if(k>n) 12 { 13 k=n; 14 if(num[n][n]==-1) 15 return num[n][n]=dp(n,n); 16 else 17 return num[n][n]; 18 } 19 else if(k==n) 20 { 21 if(num[n][k]==-1) 22 return num[n][k]=dp(n,k-1)+1; 23 else 24 return num[n][k]; 25 } 26 else 27 { 28 if(num[n][k]==-1) 29 return num[n][k]=dp(n,k-1)+dp(n-k,k); 30 else 31 return num[n][k]; 32 } 33 } 34 int main() 35 { 36 int n; 37 while(cin>>n) 38 { 39 memset(num,-1,sizeof(num)); 40 cout<<dp(n,n)<<endl; 41 } 42 return 0; 43 }