题目大意:
题目链接:http://poj.org/problem?id=2279
n
n
n个学生站成
k
k
k排,每排分别有
N
1
,
N
2
,
N
3
…
…
N
k
N1,N2,N3……Nk
N1,N2,N3……Nk名学生。要求每排的学生的身高单调递增,而每一排的同位的同学的身高单调递减。求总的方案数。
思路:
排数最多五排,所以可以考虑五维
D
P
DP
DP。
设
f
[
a
]
[
b
]
[
c
]
[
d
]
[
e
]
f[a][b][c][d][e]
f[a][b][c][d][e]表示第一排站
a
a
a人,第二排站
b
b
b人
.
.
.
...
...第五排站
e
e
e人的总方案数,那么由于人是从高到矮读入,所以,第
i
i
i行的人影响到第
i
+
1
i+1
i+1行的人,而每一行之间又有条件限制(单调性),所以状态转移方程也很容易得到了。
最终答案在
f
[
p
e
o
[
1
]
]
[
p
e
o
[
2
]
]
[
p
e
o
[
3
]
]
[
p
e
o
[
4
]
]
[
p
e
o
[
5
]
]
f[peo[1]][peo[2]][peo[3]][peo[4]][peo[5]]
f[peo[1]][peo[2]][peo[3]][peo[4]][peo[5]]中。
但是!
这样设定五维数组会
M
L
E
MLE
MLE!!!
所以我设了五维的
m
a
p
map
map储存答案。。。(时间换空间)
代码:
#include <iostream>
#include <cstring>
#include <map>
using namespace std;
unsigned int n,k,peo[6],a,b,c,d,e;
map<pair<pair<pair<pair<unsigned int,unsigned int>,unsigned int>,unsigned int>,unsigned int>,unsigned int> f;
//五维map,相当于f[31][31][31][31][31]
int main()
{
while (cin>>n) //多组数据
{
if (!n) return 0;
peo[1]=peo[2]=peo[3]=peo[4]=peo[5]=0; //初始化
for (unsigned int i=1;i<=n;i++)
cin>>peo[i];
f.clear(); //清空f数组
//相当于memset(f,0,sizeof(0));
f[make_pair(make_pair(make_pair(make_pair(0,0),0),0),0)]=1; //初始化
for (a=0;a<=peo[1];a++)
for (b=0;b<=peo[2];b++)
for (c=0;c<=peo[3];c++)
for (d=0;d<=peo[4];d++)
for (e=0;e<=peo[5];e++) //枚举每一行的人数
{
k=f[make_pair(make_pair(make_pair(make_pair(a,b),c),d),e)];
if (a<peo[1]) f[make_pair(make_pair(make_pair(make_pair(a+1,b),c),d),e)]+=k;
if (b<peo[2]&&b<a) f[make_pair(make_pair(make_pair(make_pair(a,b+1),c),d),e)]+=k;
if (c<peo[3]&&c<b) f[make_pair(make_pair(make_pair(make_pair(a,b),c+1),d),e)]+=k;
if (d<peo[4]&&d<c) f[make_pair(make_pair(make_pair(make_pair(a,b),c),d+1),e)]+=k;
if (e<peo[5]&&e<d) f[make_pair(make_pair(make_pair(make_pair(a,b),c),d),e+1)]+=k;
}
cout<<f[make_pair(make_pair(make_pair(make_pair(peo[1],peo[2]),peo[3]),peo[4]),peo[5])]<<endl;
//转移方程,每一行一个,从第二行开始受到前面一行影响,所以要多一个判断语句
}
return 0;
}