华为OJ放苹果&&整数划分

来源:互联网 发布:非线性最优化确定参数 编辑:程序博客网 时间:2024/05/01 13:52

题目描述

题目描述

把M个同样的苹果放在N个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法?(用K表示)5,1,1和1,5,1 是同一种分法。


输入

每个用例包含二个整数M和N。0<=m<=10,1<=n<=10。


样例输入

7 3


样例输出

8


/**

* 计算放苹果方法数目


* 输入值非法时返回-1

* 1 <= m,n <= 10

* @param m 苹果数目

* @param n 盘子数目数

* @return 放置方法总数

*

*/

public static int count(int m, int n)





输入描述:

输入两个int整数



输出描述:

输出结果,int型


输入例子:
7 3
输出例子   8
针对该题  设m为苹果数,n为盘子数。f(m,n)为对应的放置方法总数
(1)如果 m<n,这种情况盘子数多于水果数,这种情况与m个水果和m个盘子情形一致;
(2)m>n,水果数大于盘子数,这样可以空盘子也可以不空盘子  至少有一个空盘子的情形为f(m,n-1);没有空盘子为f(m-n,n);
至于多个空盘子的情形,在f(m,n-1)和f(m-n,n)的递归过程中会出现。
(3)m==n时,水果数与盘子数一致,与(2)类似,分每个盘子都有及至少只有一个空盘子,分f(m,n)=f(m,n-1)+f(m-n,n),但是对于f(m-n,n)m==n,此时m个水果分别放在m个盘子中,这种情况只有一种放法,所以f(m,n)=f(m,n-1)+1;
(3)终止条件:当m==1时只有一个水果,只有一种放法,n==1只有一个盘子,不管多少水果只有一种放法;都返回1
代码如下:
#include<iostream>using namespace std;int f(int m,int n)    {       if(m==1||n==1)return 1;       if(m<n)  return f(m,m);    else  if(m>n) return f(m,n-1)+f(m-n,n);
    else return 1+f(m,n-1);}int main()    {    int fruit,dis;    while(cin>>fruit>>dis)        {        cout<<f(fruit,dis)<<endl;    }    return 0;}

整数划分?

  • n=m1+m2+...+mi; (其中mi为正整数,并且1 <= mi <= n),则{m1,m2,...,mi}为n的一个划分。
  • 如果{m1,m2,...,mi}中的最大值不超过m,即max(m1,m2,...,mi)<=m,则称它属于n的一个m划分。这里我们记n的m划分的个数为f(n,m);
  • 举个例子,当n=5时我们可以获得以下这几种划分(注意,例子中<=5)

5 = 5
= 4 + 1
= 3 + 2
= 3 + 1 + 1
= 2 + 2 + 1
= 2 + 1 + 1 + 1
= 1 + 1 + 1 + 1 + 1

与放苹果类似f(n,m)n为要划分的数  m为划分时包含的最大的数
(1)n==1要划分的数为1,只有一种划分,m==1时划分中包含的最大数是1, 毫无疑问只能为有一种划分
(2)n<m即要划分的数小于划分中要包含的最大数,这种情况与f(n,n)一致;
(3)n==m这时划分时可以让最大划分数位n,也可以比n小,当最大划分数为n(m==n)时f(n,m)只有一种划分方法;
故 f(n,m)=1+f(n,m-1);
(4)n>m时同(3)的分析划分中可以包含最大划分数m也可以比m小包含m时为f(n-m,m)比m小时为f(n,m-1);
代码如下
#include<iostream>using namespace std;int f(int n,int m)    {       if(n==1||m==1)return 1;       if(n<m)  return f(n,n);    else   if(m==n)return f(m,m-1)+1;         else return f(n,m-1)+f(n-m,m);  }int main()    {    int n,m;    while(cin>>n>>m)        {        cout<<f(n,m)<<endl;    }    return 0;}
下面是刚刚参考的别人博客的内容,感觉很好

几个变种:

(一)要求1,2,3,4..,m中每个数只允许使用一次的时?

此时我们需要调整我们的状态转换公式。

f(n-m,m)+f(n,m-1); (n>m) 应该更改为:f(n-m,m-1)+f(n,m-1); (n>m)

为什呢?因为每个数最多使用一次,f(n-m,m-1)表示我们取了数m,f(n,m-1)表示我们没取,但是无论取不取数m我们以后都不会再次取数m了。

当然喽,我们还需要调整边界状态:当m=1时,f(n,m)=1;当n=1而m>1时,f(n,m)=0。

其他不变!

(二)要求只能取1,2,3,4,..,m中的奇数?(默认m为奇数,如果不是则m=m-1)

这个呢,我们首先需要调整边界状态:当m=1时,f(n,m)=1;当n=1而m>1时,f(n,m)=0

其次,我们需要调整状态转换公式:

f(n-m,m)+f(n,m-1); (n>m) 应该更改为:f(n-m,m)+f(n,m-2); (n>m)

这是因为我们不能取偶数,故而当m为奇数的时候,m-1为偶数(只能被选择0次),f(n,m-1)=f(n,m-2);




0 0
原创粉丝点击