正解:$dp$
解题报告:
先放下题目大意昂$QwQ$,就说给定$N$个人,$K$排,以及每排的人数$a_{1},...,a_{K}$,现要求每排人数递减,然后每列人数也递减,求排列方案数
显然考虑从矮到高考虑,就有一定要是满足轮廓是个凸的,就长得有点儿像之前寒假考试的搜索专题D2T5(记搜)
这题就差不多套路,考虑五维$dp$:设$f_{d_1,d_2,d_3,d_4,d_5}$,然后判断$d_1\leqslant d_2$这种之类乱七八糟的条件,然后瞎转一下,就欧克了
嗷对辣,就是,因为如果直接开$f_{30,30,30,30,30}$会炸空间,,,所以这里要对着读入开,,,啊呀说不清楚还是看$code$趴$QwQ$
#include<algorithm> #include<iostream> #include<iomanip> #include<cstring> #include<cstdio> #include<map> using namespace std; #define il inline #define gc getchar() #define int long long #define ri register int #define rb register bool #define rc register char #define rp(i,x,y) for(ri i=x;i<=y;++i) #define my(i,x,y) for(ri i=x;i>=y;--i) const int M=5+10,N=1e7; int n,as,a[M]; bool gdgs=1; il int read() { rc ch=gc;ri x=0;rb y=1; while(ch!='-' && (ch>'9' || ch<'0'))ch=gc; if(ch=='-')ch=gc,y=0; while(ch>='0' && ch<='9')x=(x<<1)+(x<<3)+(ch^'0'),ch=gc; return y?x:x; } signed main() { while(gdgs) { ri n=read();if(!n)return 0;rp(i,1,n)a[i]=read();rp(i,n+1,5)a[i]=0; int f[a[1]+1][a[2]+1][a[3]+1][a[4]+1][a[5]+1];memset(f,0,sizeof(f));f[0][0][0][0][0]=1; rp(i,1,a[1]) { rp(j,0,min(a[2],i)) { rp(k,0,min(a[3],j)) { rp(p,0,min(a[4],k)) { rp(q,0,min(a[5],p)) { if(q)f[i][j][k][p][q]+=f[i][j][k][p][q-1]; if(p-1>=q)f[i][j][k][p][q]+=f[i][j][k][p-1][q]; if(k-1>=p)f[i][j][k][p][q]+=f[i][j][k-1][p][q]; if(j-1>=k)f[i][j][k][p][q]+=f[i][j-1][k][p][q]; if(i-1>=j)f[i][j][k][p][q]+=f[i-1][j][k][p][q]; } } } } } printf("%lld\n",f[a[1]][a[2]][a[3]][a[4]][a[5]]); } return 0; }