题目大意:有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; }