淘宝面试题 放鸡蛋问题

来源:互联网 发布:java执行另一个项目 编辑:程序博客网 时间:2024/04/30 00:03

欢迎挑刺儿!!!

问题描述:有N个蛋和M个篮子,把蛋放到M个篮子里,每个篮子都不能为空。另外,需要满足:任意一个小于N的正整数,都能由某几个篮子内蛋的数量相加的和得到。写出程序,使得输入一个(N,M),输出所有可能的分配情况。

解决方法:用basket[i]表示第i个篮子放置的鸡蛋的个数。

易知,当n=1,m=1时,basket[0]=1,可满足条件。
假设 n,m 时basket[i]可满足放置条件。
则当 n+k,m+1 时,

  1. 若k<=n+1,则前边m个篮子的数量不变,basket[m]=k,即可满足条件。
    证明:即证明 n+1,n+2,……n+k 可由basket[i]表示。
    因为k<=n+1,易知n+k可由basket[i]表示。
    则n+i(i<n)可由 n 和 i 之和表示 ,又小于等于 n 的数可由basket[i]表示,又i<=n,因此n+i可由basket[i]表示。
    证毕。

  2. 若k >n+1,则basket[m]=k不能满足条件,因为无论如何都不能得到 sum(basket[i])+1(i=0,1,2……m-1)。
则只要满足k<=n+1,即k小于前m个篮子放置鸡蛋总数和,即可满足条件。

#include <iostream>#define M 50using namespace std;//将n个鸡蛋放入m个篮子void solve(int n,int m);//currentSum即代表当前前p个篮子鸡蛋总数之和//程序返回放置的总的方法个数int func(int n,int m,int p,int currentSum);//M个篮子int basket[M];int main(){int n,m;cin>>n>>m;solve(n,m);return 0;}void solve(int n,int m){if(n<m || n<0 || m<0){cout<<"无解"<<endl;return;}//第0个篮子总是放入1个鸡蛋。basket[0]=1;int num=func(n,m,1,1);if(num==0)cout<<"无解"<<endl;elsecout<<"共"<<num<<"组解"<<endl;}int func(int n,int m,int p,int currentSum){//往第m个篮子里放鸡蛋if(p==m-1){//若满足条件则打印输出if(n-currentSum>=basket[p-1] && n-currentSum <= currentSum+1){basket[p]=n-currentSum;for (int i=0;i<=p;i++){cout<<basket[i]<<"  ";}cout<<endl;return 1;}return 0;}//可能解决方案的总数int num=0;//第p个篮子可放入鸡蛋个数的最大值int e=currentSum+1 > n-currentSum ? n-currentSum : currentSum+1;//i从basket[p-1]开始,保证放置鸡蛋的个数递增,从而排除重复的情况。for (int i=basket[p-1];i<=e;i++){//第p个篮子放置鸡蛋basket[p]=i;//第p+1个篮子放置鸡蛋num+=func(n,m,p+1,currentSum+i);}return num;}