部分内容转自http://blog.csdn.net/qq675927952/article/details/6290131

题目:N个鸡蛋分到M个篮子里(N>M),不能有空篮子,对于任意不大于于N的数,保证有几个篮子的鸡蛋数和等于此数,编程实现输入N,M两个数,输出所有鸡蛋的方法

全输出的话本质就是搜索+剪枝。

(n,m,min)表示当前状态,按照篮子里蛋的数目从小到大搜索。搜到了第m个篮子,1..m个篮子面共放了n个蛋,当前的篮子放了min个蛋。下一个扩展(n+t,m+1,t),for t=min...n+1若t>n+1,则没有篮子里鸡蛋之和为n+1.

剪枝一:放n个鸡蛋后,即使后面所有的篮子都放min个,鸡蛋总数仍然超过N,按照最少的放,鸡蛋仍然不够,说明鸡蛋不够。

n+(M-m)*min>N  舍弃

剪枝二:当前鸡蛋一共n个,下个篮子最多放n+1个,依次类推:n,n+1,2n+2,4n+4,...,(n+1)*2^(M-m-1)

n+(n+1)+(n+1)*2+...+(n+1)*2^(M-m-1)=(n+1)*2^(M-m)-1<N时鸡蛋太多了。舍弃。

此时N>n*2^(M-m)+2^(M-m)-1

m=0,n=0时,N>2^M-1

 

  1. #include <iostream>    
  2.  using namespace std;    
  3.  long pow2[20];    
  4.  int N,M;    
  5.  int ans[1000];    
  6.  void solve( int n , int m , int Min )    
  7.  {    
  8.      if(n == N && m == M)    
  9.      {    
  10.        for(int i=1;i<=M;i++)    
  11.        {    
  12.          cout<<ans[i]<<" ";          
  13.        }     
  14.        cout<<endl;    
  15.        return ;          
  16.      }     
  17.      else if( n + (M-m)*Min > N || N > pow2[M-m]*n + pow2[M-m]-1)    
  18.      return ;    
  19.      else    
  20.      {    
  21.         for(int i = Min; i <= n+1; i++)    
  22.         {    
  23.            ans[m+1] =  i;        
  24.            solve(n+i,m+1,i);     
  25.         }        
  26.              
  27.      }    
  28.          
  29.           
  30.  }    
  31.      
  32.  int main()    
  33.  {    
  34.    pow2[0] = 1;    
  35.    for(int i=1;i<20;i++)    
  36.    {    
  37.      pow2[i] = pow2[i-1]<<1;           
  38.    }    
  39.      cin>>N>>M;    
  40.      if( M > N || pow2[M]-1 < N)    
  41.      {    
  42.        cout<<"没有这样的组合"<<endl;                
  43.      }           
  44.      solve( 0 , 0 , 1 );    
  45.      system("pause");        
  46.      return 0;       
  47.  }