POJ2279 Mr. Young's Picture Permutations

好久没写博客了
咕咕精又回来了!

半退役选手为了备战GDKOI不得不在肝完期末考之后牺牲半个寒假
为了找回手感先刷点水题

思路很简单
假设我们将每一个同学从小到大排列,然后把每一个同学加进来,任选一行加入到这一行末尾。
只要每次加入后都保证这一份队形是符合要求的,以后更高的人加进来也不会有任何问题。
如果当前前面有一行突出来了,那再后面要把它前面的位置补齐就只能用更高的人去补,最后就会导致凸出来的人被挡住。

题目是多组数据,然而我们不需要每次都重新算过,因为我们的每一步都符合题目要求,我们只需要打表,每次输出就好了。

代码如下:

#include
#include
using namespace std;
inline void read(int &x)
{
	x=0;register char c=getchar();
	while(c<48||57<c) c=getchar();
	for(;48<=c&&c<=57;c=getchar()) x=x*10+(c&15);
}
long long f[31][31][31][31][31];
int a[6];
void init()
{
	f[0][0][0][0][0]=1;
	for(int i=0;i<=30;i++)
		for(int j=0;j<=i;j++)
			for(int k=0;k<=j;k++)
				for(int l=0;l<=k;l++)
					for(int m=0;m<=l;m++)
					{
						if(i<30)f[i+1][j][k][l][m]+=f[i][j][k][l][m];//这一行还能站人
						if(j<i) f[i][j+1][k][l][m]+=f[i][j][k][l][m];//保证不会凸出来
						if(k<j) f[i][j][k+1][l][m]+=f[i][j][k][l][m];
						if(l<k) f[i][j][k][l+1][m]+=f[i][j][k][l][m];
						if(m<l) f[i][j][k][l][m+1]+=f[i][j][k][l][m];
					}
}
int main()
{
	init();
	int k;
	while(read(k),k)
	{
		memset(a,0,sizeof(a));
		for(int i=1;i<=k;i++)
			read(a[i]);
		printf("%lld\n",f [a[1]] [a[2]] [a[3]] [a[4]] [a[5]] );
	}
	return 0;
}

你可能感兴趣的:(动态规划,做题笔记)