欢迎挑刺儿!!!
问题描述:有N个蛋和M个篮子,把蛋放到M个篮子里,每个篮子都不能为空。另外,需要满足:任意一个小于N的正整数,都能由某几个篮子内蛋的数量相加的和得到。写出程序,使得输入一个(N,M),输出所有可能的分配情况。解决方法:用basket[i]表示第i个篮子放置的鸡蛋的个数。
易知,当n=1,m=1时,basket[0]=1,可满足条件。
假设 n,m 时basket[i]可满足放置条件。
则当 n+k,m+1 时,
则只要满足k<=n+1,即k小于前m个篮子放置鸡蛋总数和,即可满足条件。
- 若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]表示。
证毕。
- 若k >n+1,则basket[m]=k不能满足条件,因为无论如何都不能得到 sum(basket[i])+1(i=0,1,2……m-1)。
#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;
}