m个苹果放入n个盘子

方法一:分类讨论,递归
(原文参考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][n]=1;
            else if (m>n)
                dp[m][n]=dp[m][n-1]+dp[m-n][n];
            else if (m==n)
                dp[m][n]=dp[m][n-1]+1;
            else//m>n
                dp[m][n]=dp[m][m];
        }
    return dp[m][n];
}


int main()
{
    int m,n;
    while (cin>>m>>n)
        cout<<f(m,n)<<endl;
    return 0;
}
运行时间为670ms,稍长于方案二(430ms)。但是比较清楚。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章