NOJ-1203-裝盤子

Phoenix_ZengHao發表於2020-11-05

裝盤子

描述

N人為了大快朵頤,行至雲餐二樓,取了N個盤子,打了M個餃子。現欲將M個餃子裝入N個盤子中,試問共有多少種不同的裝法?
假設盤子足夠大,並且盤子裡可以什麼都不放。注意像2 5 0和5 0 2之類的屬於同一种放法。

輸入

兩個整數M、N(1=< M,N <=100)以空格隔開。

輸出

單獨一行輸出共有幾種裝法。

輸入樣例

7 3

輸出樣例

8

提示

注意輸出要以“\n”結尾。

思路

問m個餃子放到n個盤子的方法,這個題直接寫動態轉移方程不好寫,那就換成寫記憶化搜尋就行了。考慮m>=n和m<n兩種情況。dfs(int resn ,int resm)表示剩餘resn個盤子,剩餘resm個餃子的放置種類數目,dp[resn][resm]對其進行記錄,一旦dp[resn][resm]遍歷過,就直接返回即可,優化時間複雜度。m<n的話肯定有n-m個盤子都是空的ans=dfs(rem,rem)。m>=n的話可以一個盤子不妨餃子即dfs(resn-1,resm ),也可以將每個盤子都至少放一個餃子即dfs(resn,resm-resn).由dfs(resn-1,resm)不斷搜尋下去可以對不同數量的空盤子均可以遍歷到。最後答案就是dfs(n,m).

程式碼

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=100+50;
int n,m,dp[maxn][maxn];
int dfs(int resn,int resm){
    if(resn==1||resm==1||resm==0)return 1;
    if(dp[resn][resm])return dp[resn][resm];
    int ans=0;
    if(resm<resn)ans=dfs(resm,resm);
    else ans=dfs(resn-1,resm)+dfs(resn,resm-resn);
    dp[resn][resm]=ans;
    return ans;
}
int main(){
    cin>>m>>n;
    cout<<dfs(n,m)<<endl;
    return 0;
}

相關文章