题意:把一个正整数N表示为若干个正整数的和,输出有多少种表示方法。
思路:DP
思考过程是这样的。设a[1]>=a[2]>=a[3]...,因为N=a[1]+a[2]+a[3]+...。N减去a[1]后,N-a[1]成为了原问题的一个子问题。开一个二维数组DP[122][122],DP[N][M]表示正整数N的最大加数为M的分解方法数。
递归法+存储结果(0ms):
#include <iostream>
#include <stdio.h>
#include <cmath>
#include <algorithm>
#include <iomanip>
#include <cstdlib>
#include <string>
#include <memory.h>
#include <vector>
#include <queue>
#include <stack>
#include <ctype.h>
using namespace std;
int DP[122][122];
int solve(int n,int m){
if(n==0)return 1;
if(DP[n][m])return DP[n][m];
int res=0;
for(int i=1;i<=m;i++){
if((n-i)<0)break;
res+=solve(n-i,i);
}
DP[n][m]=res;
return res;
}
int main(){
int n;
memset(DP,0,sizeof(DP));
while(~scanf("%d",&n)){
cout<<solve(n,n)<<endl;
}
return 0;
}
递推法(15ms):
#include <iostream>
#include <stdio.h>
#include <cmath>
#include <algorithm>
#include <iomanip>
#include <cstdlib>
#include <string>
#include <memory.h>
#include <vector>
#include <queue>
#include <stack>
#include <ctype.h>
using namespace std;
int DP[122][122];
int solve(){
for(int i=0;i<122;i++){
DP[0][i]=1;
}
for(int i=1;i<122;i++){
for(int j=0;j<122;j++){
for(int k=0;k<=j;k++){
if((i-k)<0)break;
DP[i][j]+=DP[i-k][k];
}
}
}
}
int main(){
int n;
memset(DP,0,sizeof(DP));
solve();
while(~scanf("%d",&n)){
cout<<DP[n][n]<<endl;
}
return 0;
}
有点意外的是递归竟然比递推快,可能是递推把所有结果都计算了一遍,而递归没有,要么就是我的实现还不够好。