关于N个鸡蛋放在M个篮子里等系列问题详解
来源:互联网 发布:linux添加永久静态路由 编辑:程序博客网 时间:2024/05/01 02:51
N > M。求出满足如下要求的所有鸡蛋方法。要求:1.篮子不能为空;2.对于任意正整数n<=N, 能取x个篮子,使篮子里的鸡蛋数总和等于n。
2.当前篮子放n个鸡蛋,下一个篮子放鸡蛋的个数为Min~n+1,也就是最多放n+1个,再下一个篮子最多放2n+2,4n+4...(n+1)*2^(M-m-1)
当前篮子放n个,如果以后按最多的放,所有篮子的鸡蛋总和如果小于N,说明鸡蛋太多,放不完,要剪枝。即
n+(n+1)(2^0+2^1+2^2+2^3+...+2^(M-m-1))<N
化简得:
N > pow2[M-m]*n + pow2[M-m]-1
实现方法一:
#include <cstring>#include <iostream>//namespace al{int min(int x, int y){return x<=y?x:y;}void egg (int n, int m, int *&a,int size){ // n是鸡蛋数,m是篮子数,a数组用来存储结果,size是a数组的大小for (int i=min((n+1)/2, a[m]); i>=1; --i){if (n<m) {continue;}else if (n == m){for (int j=m-1; j>=0; --j){a[j] = 1;}m = 1;n = 0;}if (m == 1) {if (n > 1) {continue;}else{for (int k=0; k<size; ++k)std::cout<<a[k]<<" ";std::cout<<std::endl;return ;}} else {a[m-1] = i;egg (n-i, m-1, a, size);}}}//} //namespace alint main(){int n=20;int m=10;int* a = new int[m];a[0] = 1;int *&aa = a;for (int i=(n+1)/2; i>=1; --i){ //由于egg函数中有i=min((n+1)/2, a[m])这句,所以数组最后一位是a[m-1],不存在a[m],所以这里初始处理下memset(a, 0, m);a[m-1] = i;//al::egg (n-i, m-1, aa, m);}}
实现方法二:
#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=0;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] = 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; }
说明:
1.n + (M-m)*Min > N 剪枝条件:放n个鸡蛋后,后面的篮子里即使都放Min个,总鸡蛋数都超过了N个。说明鸡蛋太少了2.当前篮子放n个鸡蛋,下一个篮子放鸡蛋的个数为Min~n+1,也就是最多放n+1个,再下一个篮子最多放2n+2,4n+4...(n+1)*2^(M-m-1)
当前篮子放n个,如果以后按最多的放,所有篮子的鸡蛋总和如果小于N,说明鸡蛋太多,放不完,要剪枝。即
n+(n+1)(2^0+2^1+2^2+2^3+...+2^(M-m-1))<N
化简得:
N > pow2[M-m]*n + pow2[M-m]-1
此外main函数里的判断pow2[M]-1 < N也是按照这个思路推导的。
实现方法三:
#include <iostream>using namespace std;#define MAX_M 32int ar[ MAX_M + 1 ];int egg = 9 , box = 5;void place_egg( int n , int m , int max ){ if( m == 1 ) { ar[ 1 ] = n; for( int i = 1 ; i <= box ; i++ ) cout << " " << ar[ i ]; cout << endl; return; } if( m > n || n > ( 1 << m ) - 1 ) return; if( ( n + 1 ) / 2 < max ) max = ( n + 1 ) / 2; for( int i = max ; i >= ( n + m - 1 ) / m ; i-- ) { ar[ m ] = i; place_egg( n - i , m - 1 , i ); }}int main(){ place_egg( egg , box , egg ); return 0;}
实现方法四:
/** * 假设 n>m 并且 n小于100 * @author Jason * 2011.3.30 */ public class Test { private int m; private int n; private int eggs[]; private int numAnswer; Test(){ m=10; n=20; numAnswer=0; eggs = new int[m]; for(int i=0;i<m;i++){ eggs[i]=0; } } private void fill(boolean [] state, int step, int sum){ if(step>=m){ state[sum] = true; return ; } fill(state,step+1,sum); fill(state,step+1,sum+eggs[step]); } /** * 判断是否满足:任意一个小于N的正整数,都能由某几个篮子内蛋的数量相加的和得到 * 算法:暴力枚举所有篮子的组合 * @return */ private boolean judge(){ boolean [] state = new boolean [n+1]; for(int i=0;i<=n;i++){ state[i] = false; } fill(state,0,0); for(int i=1;i<=n;i++){ if(!state[i]){ return false; } } return true; } /** * 给每个篮子分鸡蛋,升序(后一个篮子的鸡蛋必须不小于前一个篮子,避免重复计算) * @param pre 前一个篮子鸡蛋数 * @param already 前step个篮子 已使用的鸡蛋数 * @param step 第step个篮子 */ public void solve(int pre,int already, int step){ if(step==m-1){ //最后一个篮子 eggs[m-1]=n-already; //不符合条件 if(eggs[m-1]<pre) return; //判断是否满足:任意一个小于N的正整数,都能由某几个篮子内蛋的数量相加的和得到 if(judge()) { for(int i=0;i<m;i++){ System.out.print(eggs[i]+" "); } System.out.println(); numAnswer++; } return ; } // 给第step个篮子装鸡蛋,pre 到 n-already 种可能 for(int i=pre; i<=n-already; i++){ eggs[step]=i; //递归 solve(i,already+i,step+1); } } public static void main(String arg [] ){ Test test = new Test(); test.solve(1,0,0); System.out.println("可能情况的数量:"+test.numAnswer); } }
- 关于N个鸡蛋放在M个篮子里等系列问题详解
- 关于N个鸡蛋M个篮子
- N个鸡蛋分到M个篮子里
- 回溯法_求N个鸡蛋分到M个篮子里问题
- 164 求N个鸡蛋分到M个篮子里问题
- N个鸡蛋放进M个篮子问题
- N个鸡蛋放进M个篮子问题
- N个鸡蛋M个篮子
- N个鸡蛋放M个篮子,每个篮子不空,保证提不同组合的篮子能取出1至N个鸡蛋
- N个鸡蛋放到M个篮子中
- N个鸡蛋放到M个篮子中,篮子不能为空
- 【C++】m个苹果放在N个盘子里
- N个鸡蛋放入M个篮子且能组合出1~N所有的数
- 把鸡蛋放在一个篮子里了,呜呜。。。!
- 把n个同样的苹果放在m个同样的盘子里
- 把M个同样的苹果放在N个同样的盘子里
- 数学之美 系列十六 不要把所有的鸡蛋放在一个篮子里 -- 谈谈最大熵模型
- 【数学之美 系列十六】 不要把所有的鸡蛋放在一个篮子里 -- 谈谈最大熵模型
- 私人公司并购凭什么就可改变未来国际软件市场竞争格局?
- 腾讯:小狗喝药判断哪瓶有毒和实现数组特定值
- sql 截取字符串
- js获取scrollbar的默认宽度
- URL转码
- 关于N个鸡蛋放在M个篮子里等系列问题详解
- 2011-8-24
- 关于KernelFaultCheck启动项
- 动态控件的创建和使用--动态按钮
- GetRegionData这个函数真难用
- Android中模拟器如何访问本地服务器
- (转) epoll的LT和ET模式的区别
- 初涉多线程与socket
- Android应用开发——系统自带样式Android:theme