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)。但是比較清楚。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章