【POJ 2279】Mr. Young's Picture Permutations【DP】

题目大意:

题目链接:http://poj.org/problem?id=2279
nn个学生站成kk排,每排分别有N1,N2,N3NkN1,N2,N3……Nk名学生。要求每排的学生的身高单调递增,而每一排的同位的同学的身高单调递减。求总的方案数。


思路:

排数最多五排,所以可以考虑五维DPDP
f[a][b][c][d][e]f[a][b][c][d][e]表示第一排站aa人,第二排站bb......第五排站ee人的总方案数,那么由于人是从高到矮读入,所以,第ii行的人影响到第i+1i+1行的人,而每一行之间又有条件限制(单调性),所以状态转移方程也很容易得到了。
最终答案在f[peo[1]][peo[2]][peo[3]][peo[4]][peo[5]]f[peo[1]][peo[2]][peo[3]][peo[4]][peo[5]]中。
但是!
这样设定五维数组会MLEMLE!!!
所以我设了五维的mapmap储存答案。。。(时间换空间)


代码:

#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;
}
posted @ 2018-08-18 11:53  全OI最菜  阅读(56)  评论(0编辑  收藏  举报