POJ 2279

题目大意:有N个学生合影,站成左端对齐的k排,每排分别有N1,N2,......,Nk个人,第1排站在最后边,第k排站在最前边。学生的身高互不相同,把他们从高到低依次标记为1,2,......,N。在合影时要求每一排从左到右身高递减,每一列从后到前身高也递减,问一共有多少种安排合影位置的方案?

分析:这是lyd大神的经典dp题。也可以说是一个暴力题,看看代码估计就懂了。

代码:

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int maxn = 31;
typedef long long ll;
int n[6];
int main() {
    int k;
    while (cin >> k) {
        if (!k) break;
        for (int i = 0; i < 6; i++)
            n[i] = 0;
        for (int i = 1; i <= k; i++)
            cin >> n[i];
        ll dp[n[1] + 1][n[2] + 1][n[3] + 1][n[4] + 1][n[5] + 1];//这样定义数组是直接全局不知道为什么就MLE了。
        memset(dp, 0, sizeof(dp));
        dp[0][0][0][0][0] = 1;//每维均为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++) {
                            if (a1 < n[1]) dp[a1 + 1][a2][a3][a4][a5] += dp[a1][a2][a3][a4][a5];//如果第一维小于n[1],就还可以往第一排安排人。
                            if (a1 > a2 && a2 < n[2]) dp[a1][a2 + 1][a3][a4][a5] += dp[a1][a2][a3][a4][a5];//如果第一维人数大于第二维人数并且第二维人数小于n[2],就可以在第二排安排人。
                            if (a1 > a3 && a2 > a3 && a3 < n[3]) dp[a1][a2][a3 + 1][a4][a5] += dp[a1][a2][a3][a4][a5];
                            if (a1 > a4 && a2 > a4 && a3 > a4 && a4 < n[4])
                                dp[a1][a2][a3][a4 + 1][a5] += dp[a1][a2][a3][a4][a5];
                            if (a1 > a5 && a2 > a5 && a3 > a5 && a4 > a5 && a5 < n[5])
                                dp[a1][a2][a3][a4][a5 + 1] += dp[a1][a2][a3][a4][a5];
                        }
                    }
                }
            }
        }
        cout << dp[n[1]][n[2]][n[3]][n[4]][n[5]] << endl;
    }
    return 0;
}
posted @ 2020-01-15 19:48  SwiftAC  阅读(148)  评论(0编辑  收藏  举报