# POJ2279_Mr. Young's Picture Permutations

题意略

可见k的取值小于等于5,所以不妨只考虑k的值为5的情况,

若k小于5,令多出来的每行N为0即可转化为k=5的情况

发现,当我们从1到n依次考虑放置学生在哪个位置时,学生高矮的单调性就得到了满足

所以,考虑这样一种dp方案:

令dp[a1][a2][a3][a4][a5]表示第1行已经放了a1个学生,第2行已经放了a2个学生,第3行已经放了a3个学生...的列队方案数

考虑这个状态可以向哪些状态转移

第i个学生可以站在如下的位置:

1、站在第一行的最右

2、站在第k行的最右,并满足\(a_{k} < a_{k - 1},并且\ a_{k} < N_{k}\)


总结以下,转移是这样的:

初始化:\(f[0][0][0][0][0] = 1\)

转移:

考虑第1行,\(f[a1+1][a2][a3][a4][a5]+=f[a1][a2][a3][a4][a5]\)

考虑第k行(2<=k<=5)\(f[...ak + 1....]+=f[a1][a2][a3][a4][a5](a_{k}<a_{k-1}\ \&\&\ a_{k}<N_{k})\)

答案:\(f[N1][N2][N3][N4][N5]\)


代码:

// #include <bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
#include <cstring>
using namespace std;
int k;
int N[10];
unsigned int f[31][16][11][8][7];

int main() {
    while (cin >> k && k) {
        memset(N, 0, sizeof N);
        memset(f, 0, sizeof f);
        for (int i = 1; i <= k; i++)
            scanf("%d", &N[i]);

        f[0][0][0][0][0] = 1;
        for (int a1 = 0; a1 <= N[1]; a1++)
        for (int a2 = 0; a2 <= N[2]; a2++)
        for (int a3 = 0; a3 <= N[3]; a3++)
        for (int a4 = 0; a4 <= N[4]; a4++)
        for (int a5 = 0; a5 <= N[5]; a5++) {
            int now = f[a1][a2][a3][a4][a5];
            if (a1 < N[1]) f[a1 + 1][a2][a3][a4][a5] += now;
            if (a2 < N[2] && a2 < a1) f[a1][a2 + 1][a3][a4][a5] += now;
            if (a3 < N[3] && a3 < a2) f[a1][a2][a3 + 1][a4][a5] += now;
            if (a4 < N[4] && a4 < a3) f[a1][a2][a3][a4 + 1][a5] += now;
            if (a5 < N[5] && a5 < a4) f[a1][a2][a3][a4][a5 + 1] += now; 
        }

        cout << f[N[1]][N[2]][N[3]][N[4]][N[5]] << endl;
    }
}
posted @ 2020-08-20 21:30  熹圜  阅读(88)  评论(0)    收藏  举报