整数拆分问题
原创
©著作权归作者所有:来自51CTO博客作者Stven_King的原创作品,请联系作者获取转载授权,否则将追究法律责任
1 = 1;
2 = 2;
2 = 1 + 1;
3 = 3;
3 = 2 + 1;
3 = 1 + 1 + 1;
4 = 4;
4 = 3 + 1;
4 = 2 + 2;
4 = 2 + 1 + 1;
4 = 1 + 1 + 1 + 1;
5 = 5;
5 = 4 + 1;
5 = 3 + 2:
5 = 3 + 1 + 1;
5 = 2 + 2 + 1;
5 = 2 + 1 + 1 + 1;
5 = 1 + 1 + 1 + 1 + 1;6 = 6;
6 = 5 + 1;
6 = 4 + 2;
6 = 4 + 1 + 1;
6 = 3 + 3
6 = 3 + 2 + 1;
6 = 3 + 1 + 1 + 1;
6 = 2 + 2 + 2;
6 = 2 + 2 + 1 + 1;
6 = 2 + 1 + 1 + 1 + 1;
6 = 1 + 1 + 1 + 1 + 1 + 1;
在5的式子中,以5开头的式子有1个,4开头的式子有1个,三开头的式子有2个,2开头的式子有2个,1开头的式子有1个;
实际上如果以4开头,则剩下1(5-4)将被分割,1只有一种分割情况(1 =1),所以4开头的式子有1个;
同样,3开头的情况,剩下2(5-3)将被分割,2有两种分割情况(2 =2; 2 = 1 + 1;),所以3开头的式子有2个;
但是,2开头的情况有点不同,因为剩下3将被分割,但是3有3种分割式子,我们发现其中一种分割情况是将3分割成 3 = 3;
如果将这种情况算入2开头的式子总数,(式子就会变成这样5 = 2 + 3),这会违反我们开头的约定(递减排列加数),所以我们将这一条式子去掉;
同理,1开头的情况,只有一种情况,这是4的分割方法去掉所有加数大于1的式子数目得到的,但是我们也可以直接得出1,因为 这种情况太简单,我们可以直接得出结论。
通过分析我们可以得出一个式子当k小于的n时候:
f(n,k)=f(n,k-1)+f(n-k,k) //重点式子;
举个例子:f(6,4)的划分可以看做是f(6,3)的划分
再加上f(2,4)即(f(2,2))的划分。
当k等于n的时候f(n,k)=f(n,k-1)+1;
最后还有就是f(n,1)=1;
这样我们就可以产生一个递推的关系式。。。。。
用函数这样表示:
int init(int n,int m)
{
if(n==1||m==1)
return 1;
else if(n==m)
return init(n,n-1)+1;
else
return init(n,m-1)+init(n-m,n-m);
}
这样我们也可以用一个数组计算并保存
int n[N][N];
void init(){
int i,j;
for(i=0;i<N;i++)
n[i][1]=n[1][i]=1;
for(i=2;i<N;i++){
for(j=2;j<N;j++){
if(i>j)
n[i][j]=n[i][j-1]+n[i-j][j];
else if(i==j)
n[i][j]=1+n[i][j-1];
else
n[i][j]=n[i][i];
}
}
}
其中f(n,n)=n[n][n];
这样用于多输出也比较方便一些.......