划分问题

来源:互联网 发布:网络语言的特点 编辑:程序博客网 时间:2024/05/16 17:59

http://www.cnblogs.com/hustcat/archive/2009/06/16/1504604.html

#include <stdio.h>
/*******************************************************************/
/*整数划分问题:
**将正整数n表示成一系列正整数之和:n=n1+n2+…+nk,
**其中n1>=n2>=…>=nk>=1,k>=1。
**正整数n的这种表示称为正整数n的划分。求正整数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。
*/
/************************************************************************/
                                                                     
/************************************************************************/
/*算法:
**记q(n,m)表示n的最大加数n1不大于m的划分个数,则有:
**       |-    1     ,n=1,m=1
**q(n,m)=|  q(n,n)   ,n<m
**       | 1+q(n,n-1),n=m  ,n的划分由n1=n的划分和n1<=n-1的划分组成
**       |_ q(n-m,m)+q(n,m-1),n>m>1,n的最大加数n1不大于m的划分由n1=m的划分和n1<=m-1的划分组成
*/
/*******************************************************************/
int int_partion(int n,int m)
{
    
if(n==1||m==1)
        
return 1;
    
else if(n<m)
        
return int_partion(n,n);
    
else if(n==m)
        
return 1+int_partion(n,n-1);
    
else
        
return int_partion(n-m,m)+int_partion(n,m-1);
}

/*非递归算法*/
#define N 6
int S[N+1][N+1];
int int_partion_2(int n,int m)
{
    
int i,j;
    
for (i=1;i<=n;i++)
    {
        S[i][
1]=1;
        S[
1][i]=1;
    }
    
for (i=2;i<=n;i++)
    {
        
for (j=2;j<=m;j++)
        {
            
if(i==j)
                S[i][j]
=1+S[i][i-1];
            
else if(i<j)
                S[i][j]
=S[i][i];
            
else
                S[i][j]
=S[i-j][j]+S[i][j-1];
        }
    }
    
return S[n][m];
}
/*******************************************************************/
/*集合划分问题:
**n个元素{1,2,,n}可以划分为多少个非空子集。该值实际上为Bell数,记为B(n)。
**例如:{1,2,3}的划分:
**{{1,2,3}}, {{1,2},{3}}, {{1,3},{2}}, {{1},{2,3}}
*/
/*******************************************************************/
/************************************************************************/
/*算法:
**记s(n,m)表示n个元素集合可以划分为m个非空子集的数量,该数实际上是Stirling数,则有:
**s(n,m)=m*s(n-1,m)+s(n-1,m-1); s(n,n+1)=0,s(n,0)=0,s(0,0)=1。
**显然:B(n)=s(n,1)+s(n+2)++s(n,n)
*/
/*******************************************************************/

//计算stirling数
int stirling(int n,int m)
{
    
int min,i,j;
    S[
0][0]=1;
    
for (i=1;i<=n;i++)
        S[i][
0]=0;
    
for(i=0;i<n;i++)
        S[i][i
+1]=0;
    
for (i=1;i<=n;i++)
    {
        
if(i<m)
            min
=i;
        
else
            min
=m;
        
for(j=1;j<=min;j++)
            S[i][j]
=j*S[i-1][j]+S[i-1][j-1];
    }
    
return S[n][m];
}

//计算bell数
int bell(int n)
{
    
int num=0;
    stirling(n,n);
    
for (int i=1;i<=n;i++)
    {
        num
+=S[n][i];
    }
    
return num;
}
int main()
{
    
int n=4,m=2;
    
//printf("%d pation numbers are:%d\n",n,int_partion_2(n,n));
    printf("%d,%d sirling number is:%d\n",n,m,stirling(n,m));
    
    printf(
"%d bell number is:%d\n",n,bell(n));
    
return 0;
}

原创粉丝点击