# 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;
}
}

浙公网安备 33010602011771号