题目大意:
给定N个学生,k排,每排分别有N1,N2,N3……Nk
合影时要求每一排从左到右身高递减,每一列从后到前身高也递减,问一共有多少种安排合影位置的方案
解题思路:
五维dp
f[a1,a2,a3,a4,a5]表示各排从左端起分别占了a1,a2,a3,a4,a5个人时合影方案数量
然后我们枚举a1,a2,a3,a4,a5从0开始到N1,N2……N5
若a1 < N1
若a2 < N2&a1 > a2
若a3 < N3&a2 > a3
……(以此类推)
额,这题还可以用一种我不会的数学解法:
“杨氏矩阵”+“勾长公式”
百度一下这个题目似乎用数学解法的人还挺多的
Accepted code:
#include<cstdio>
#include<algorithm>
#include<cctype>
#include<cstring>
#include<iostream>
#define r(i,a,b) for(int i=a;i<=b;i++)
#define N 31
using namespace std;
int t,n[6];
inline void read(int &f) {
f=0; char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) f=(f<<3)+(f<<1)+c-48,c=getchar();
return;
}
inline bool init(){
read(t); if (t==0) return 0;
r(i,1,t)
read(n[i]);
r(i,t+1,5) n[i]=0; return 1;
}
inline unsigned int dp() {
unsigned int f[n[1]+1][n[2]+1][n[3]+1][n[4]+1][n[5]+1];
memset(f,0,sizeof(f));
f[0][0][0][0][0]=1;
r(i1,0,n[1])
r(i2,0,n[2])
r(i3,0,n[3])
r(i4,0,n[4])
r(i5,0,n[5]) {
if (i1<n[1])
f[i1+1][i2][i3][i4][i5]+=f[i1][i2][i3][i4][i5];
if (i2<n[2]&&i1>i2)
f[i1][i2+1][i3][i4][i5]+=f[i1][i2][i3][i4][i5];
if (i3<n[3]&&i2>i3)
f[i1][i2][i3+1][i4][i5]+=f[i1][i2][i3][i4][i5];
if (i4<n[4]&&i3>i4)
f[i1][i2][i3][i4+1][i5]+=f[i1][i2][i3][i4][i5];
if (i5<n[5]&&i4>i5)
f[i1][i2][i3][i4][i5+1]+=f[i1][i2][i3][i4][i5];
}
return f[n[1]][n[2]][n[3]][n[4]][n[5]];
}
int main() {
while(init())
cout<<dp()<<endl;
}