您的位置:首页 > 其它

m个苹果放入n个盘子

2014-02-15 19:21 260 查看
方法一:分类讨论,递归

(原文参考http://blog.csdn.net/yangliuy/article/details/7251383)

问题描述:将m个苹果放进n个盘子中,盘子允许空,有多少种方法。同时注意例如1、2和2、1这两种方案是一种方案。

通过分类讨论,将规模较大的问题转换成规模较小的相同问题,学会”降维“,将索引值不断降小,就可以递归求解。

设f(m,n)为把m个苹果放到n个盘子中的方法数,m>=0,n>=0.

若m和n中任何一个等于0,那么f(m,n) = 1,注意不是等于0,因为相当于就那么一种结果,就是不往盘子里面放(没有苹果),或者,连盘子都没有。

若n=1,显然对于任意的m>=0 有f(m,1) = 1

若m=1,显然对于任意的n>=0 有f(1,n) = 1

接下来讨论m>1 && n>1的情况:

若 m < n 则 f(m,n) = f(m,m)。即空哪几个盘子都是一样的

若 m>=n 则 大体有两种放法:

第1种情况:至少有一个盘子为空,即什么也不放,这部分的方法数为f(m,n-1);

第2种情况:全部盘子都有苹果,那么先从m个苹果中抽取出n个出来,各个盘子分一个,考虑剩下的m-n个苹果放到n个盘子里的放法,这样就成功把f(m,n)降到了f(m-n,n)。

所以,m>=n时,有f(m,n) = f(m,n-1) + f(m-n,n);

代码如下:

#include

using namespace std;

int f(int x,int y)

{

    if (x==0||y==1) return 1;

    if (x<y) return f(x,x);

    return f(x,y-1)+f(x-y,y);//至少一个盘子为空或者每个盘子都放了苹果

}

int main()

{

    int m,n;

    while (cin>>m>>n)

          cout<<f(m,n)<<endl;

    return 0;

}

但是以上方法会严重超时,当m,n>100时,程序运行时间t>10s

方法二:动态规划

#include

using namespace std;

const int lmax=10000;

int c1[lmax+1],c2[lmax+1];

int main()

{

    int m,n,i,j,k;

    while(cin>>m>>n)

    {

        if (m

            n=m;

        for(i=0;i<=m;i++)

        {

            c1[i]=1;

            c2[i]=0;

        }

        for(i=2;i<=n;i++)//盘子数 

        {

            for(j=0;j<=m;j++)//苹果数 

                for(k=0;k+j<=m;k+=i)

                {

                    c2[j+k]+=c1[j];

                }

            for(j=0;j<=m;j++)

            {

                c1[j]=c2[j];

                c2[j]=0;

            }

        }

        cout<<c1[m]<<endl;

    }

}

当m,n>100,运行时间t<1000ms。这个程序没有看很懂。

方法三:方法一的修改版

#include <iostream>

using namespace std;

int f(int m,int n)

{

    int dp[101][101];

    for (int m=1;m<=100;++m)

        for (int n=1;n<=100;++n)

        {

            if (m==1||n==1)

                dp[m]
=1;

            else if (m>n)

                dp[m]
=dp[m][n-1]+dp[m-n]
;

            else if (m==n)

                dp[m]
=dp[m][n-1]+1;

            else//m>n

                dp[m]
=dp[m][m];

        }

    return dp[m]
;

}

int main()

{

    int m,n;

    while (cin>>m>>n)

        cout<<f(m,n)<<endl;

    return 0;

}

运行时间为670ms,稍长于方案二(430ms)。但是比较清楚。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: