Acwing 271. 楊老師的照相排列(線性dp求方案數)

Acwing 271. 楊老師的照相排列

題目

有 n 個人,編號 1 ~ n。要站成 k 排,現在給出每排的人數,保證從前往後不遞增。現在給出總人數,求符合要求的總方案數。

分析

https://www.bilibili.com/video/av69678938

根據閆氏 dp 分析法,做 dp 先要劃分集合,弄清除每個集合代表的意義。

dp[a][b][c][d][e]dp[a][b][c][d][e] 代表 5 排人數分別爲 a, b, c, d, e,時的方案數,這時 dpdp 數組的每個元素代表一種特定的輪廓方案數的集合。枚舉集合最後一個元素位置,劃分集合。

進而得出狀態轉移方程。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll INF = 0x3f3f3f;
const int N = 31;

int k, s[5];
ll dp[N][N][N][N][N];

int main() {
    while (scanf("%d", &k), k) {
        memset(s, 0, sizeof(s));
        memset(dp, 0, sizeof(dp));
        for (int i = 0; i < k; i++) 
            scanf("%d", &s[i]); 
        dp[0][0][0][0][0] = 1;
        for (int a = 0; a <= s[0]; a++)
            for (int b = 0; b <= min(s[1], a); b++)
                for (int c = 0; c <= min(s[2], b); c++) 
                    for (int d = 0; d <= min(s[3], c); d++)
                        for (int e = 0; e <= min(s[4], d); e++) {
                            ll &v = dp[a][b][c][d][e];
                            if (a && a - 1 >= b) v += dp[a-1][b][c][d][e];
                            if (b && b - 1 >= c) v += dp[a][b-1][c][d][e];
                            if (c && c - 1 >= d) v += dp[a][b][c-1][d][e];
                            if (d && d - 1 >= e) v += dp[a][b][c][d-1][e];
                            if (e) v += dp[a][b][c][d][e-1];
                        }
        printf("%lld\n", dp[s[0]][s[1]][s[2]][s[3]][s[4]]);
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章