[Luogu 2386]放蘋果

Description

題庫連接c++

\(n\) 個一樣的蘋果放在 \(m\) 個一樣的盤子裏,容許有的盤子空着不放,問共有多少種不一樣的分發。多測,數據組數 \(t\)spa

\(1\leq m,n\leq 10, 1\leq t\leq 20\)code

Solution

康復訓練 \(\times 3\)ip

下午給學弟講課時發現了這樣一道題...數據徹底能夠出到 \(O(n^2)\)固然原題的意思是要用搜索作...get

咱們記 \(f_{i,j}\)\(i\) 個蘋果放在 \(j\) 個盤子中的方案數。顯然邊界條件爲 \(\forall i,f_{0,i}=1\),理由是沒有蘋果時局面只有一種,即任何盤子都爲空。it

要注意到這樣一個性質,因爲盤子均相同,因此 \(f_{i,j}=f_{i,i},j>i\)io

對於 \(\text{DP}\) 方程,考慮第 \(j\) 個盤子怎麼放。class

  1. 若第 \(j\) 個盤子不放蘋果,那麼只需考慮 \(i\) 個蘋果放在 \(j-1\) 個盤子中的方案數,即 \(f_{i,j-1}\)
  2. 若第 \(j\) 個盤子放蘋果,由常規套路 \(\text{DP}\) 時由無序變有序,盤子放蘋果數單調遞減。那麼若是最後一個盤子都有蘋果,則全部盤子都有蘋果。咱們將每一個盤子中的蘋果數均 \(-1\),就變成了通常狀況。此時方案數爲 \(f_{i-j,j}\)

綜上方程爲 \(f_{i,j}=f_{i,j-1}+f_{i-j,j}\)搜索

Code

#include <bits/stdc++.h>
using namespace std;
const int N = 50;

int f[N][N], n, m, t;

int main() {
    for (int i = 0; i < 50; i++) f[0][i] = 1;
    for (int i = 1; i < 50; i++)
        for (int j = 1; j < 50; j++) {
            if (j > i) f[i][j] = f[i][i];
            else f[i][j] = f[i][j-1]+f[i-j][j];
        }
    scanf("%d", &t);
    while (t--) {
        scanf("%d%d", &m, &n);
        printf("%d\n", f[m][n]);
    }
    return 0;   
}
相關文章
相關標籤/搜索