部分内容转自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
- #include <iostream>
- using namespace std;
- long pow2[20];
- int N,M;
- int ans[1000];
- void solve( int n , int m , int Min )
- {
- if(n == N && m == M)
- {
- for(int i=1;i<=M;i++)
- {
- cout<<ans[i]<<" ";
- }
- cout<<endl;
- return ;
- }
- else if( n + (M-m)*Min > N || N > pow2[M-m]*n + pow2[M-m]-1)
- return ;
- else
- {
- for(int i = Min; i <= n+1; i++)
- {
- ans[m+1] = i;
- solve(n+i,m+1,i);
- }
- }
- }
- int main()
- {
- pow2[0] = 1;
- for(int i=1;i<20;i++)
- {
- pow2[i] = pow2[i-1]<<1;
- }
- cin>>N>>M;
- if( M > N || pow2[M]-1 < N)
- {
- cout<<"没有这样的组合"<<endl;
- }
- solve( 0 , 0 , 1 );
- system("pause");
- return 0;
- }
转载于:https://blog.51cto.com/buptdtt/827954