淘宝面试题 放鸡蛋问题

欢迎挑刺儿!!!

问题描述:有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 50
using 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;
	else
		cout<<"共"<<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;
}





你可能感兴趣的:(淘宝面试题 放鸡蛋问题)