题目链接:https://vjudge.net/problem/POJ-2279
(学校的大作业什么的终于弄完了........
用f[a][b][c][d][e]表示五行分别站了a,b,c,d,e人时的总方案数。可以想成从高度最低的人开始依次放置,那么如果a处能放,必然有a>b;如果b处能放,必然有b<=a且b>c,c,d,e同理。由此可以得到转移方程(比较长,见代码)。有一个小问题,如果开f[31][31][31][31][31]的话内存不够,但是由于前一行的人数一定>=后一行,所以可以按照每行站的最多人数来开数组f[31][16][11][8][7]
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 #include<cstring> 3 #define ll long long 4 using namespace std; 5 6 ll f[31][16][11][8][7]; 7 int x[10],a,b,c,d,e,n,i; 8 9 void dp(){ 10 f[0][0][0][0][0]=1; 11 for (a=0;a<=x[1];a++) 12 for (b=0;b<=min(a,x[2]);b++) 13 for (c=0;c<=min(b,x[3]);c++) 14 for (d=0;d<=min(c,x[4]);d++) 15 for (e=0;e<=min(d,x[5]);e++){ 16 if (a>b) f[a][b][c][d][e]+=f[a-1][b][c][d][e]; 17 if (b>c) f[a][b][c][d][e]+=f[a][b-1][c][d][e]; 18 if (c>d) f[a][b][c][d][e]+=f[a][b][c-1][d][e]; 19 if (d>e) f[a][b][c][d][e]+=f[a][b][c][d-1][e]; 20 if (e>0) f[a][b][c][d][e]+=f[a][b][c][d][e-1]; 21 } 22 cout<<f[x[1]][x[2]][x[3]][x[4]][x[5]]<<endl; 23 } 24 25 int main(){ 26 //freopen("poj2279.txt","r",stdin); 27 cin>>n; 28 while (n!=0){ 29 memset(x,0,sizeof(x)); 30 for (i=1;i<=n;i++) cin>>x[i]; 31 memset(f,0,sizeof(f)); 32 dp(); 33 cin>>n; 34 } 35 return 0; 36 }