整数划分问题(苹果盘子问题)

来源:互联网 发布:诸葛亮马前课指算法图 编辑:程序博客网 时间:2024/05/22 21:51
整数划分问题

       整数划分问题是算法中的一个经典命题之一,有关这个问题的讲述在讲解到递归时基本都将涉及。所谓整数划分,是指把一个正整数n写成如下形式:

       n=m1+m2+...+mi; (其中mi为正整数,并且1 <= mi <= n),则{m1,m2,...,mi}为n的一个划分。

递归法:

递推表达式如下:

         f(n, m)=       1;                                (n=1 or m=1)    //1划分为m份,或n划分为1份

                            f(n, n);                         (n<m)  

                            1+ f(n, m-1);                (n=m) //分成的份数中没有为0的(即全为1相加),有0的则为f(n,m-1)划分

                            f(n-m,m)+f(n,m-1);       (n>m)

 

 

实例应用:7个苹果放入三个盘子(无重复).

第一类: n个苹果放入m个盘子中,三个盘子都不为空,每个盘子先放一个,问题等同于n-m个苹果放入m个盘子中,即为d(n-m,m);
第二类: n个苹果放入m个盘子中,三个盘子有一个盘子为空,则等同于n个苹果再放入m-1个盘子,即d(n,m-1);

 

#include<stdio.h>
#include<string>
int partitionHelp(int n,int m)
{
    if(n<1 ||m<1)
    {
        return 0;
    }
    else if(n==1 ||m==1)
    {
        return 1;
    }
    else if(n<m)
    {
        return partitionHelp(n,n);
    }
    else if(n==m)
    {
        return 1+partitionHelp(n,n-1);
    }
    else
    {
        return partitionHelp(n,m-1)+partitionHelp(n-m,m);
    }

}


void main()
{
int number = 0;
number = partitionHelp(7,3);
printf("%d\n",number);
}

 

下面的另一解法从网上寻得:

 

 #include <iostream>  
 using namespace std; 
  
 int a[10]={0}; 
 int len = 0; 
 int count = 0;
 
 void fun(int n,int m){   
     if(n==0){              //所求数已被全部分划 
     count++;
    cout<<a[0]; 
     for(int i=1;i<m;++i)  
        cout<<"+"<<a[i]; 
     if(m > len){ 
         cout<<endl;    //到每行最后一列长度m都为len+1,此时应换行 
         ++len; 
 

    else 
         cout<<","; 
   return; 

     for(int i=n;i>=1;--i){     //按从大到小的顺序划分整数 
         if(m==0||i<=a[m-1]) {   //右边的数不能大于左边的数 
         a[m]=i; 
         fun(n-i,m+1); 



  
 int main() {  
     int n,m=0;  
     cin>>n;            //输入一个1-10的整数 
     fun(n,m);        //递归的方法打印所有的整数分划 
  cout << endl << "总数目: " << count << endl;
     return 0; 
}