题目大意:有n个人,他们的身高依次升高,按照高矮高矮高矮.........的这种波形顺序排列求一共有多少种方法!
解题思路:唉,搜索和dp对我都是硬伤,比赛时看了一下,根本就是无从下手,不知道动态转移方程式什么!下来问了别人,然后思考了一下,OMG!原来方程这么简单。首先我们假设已知前i-1,i-2,...1,个人排列数。然后我们来插入第i个人,由于第i个人是前i个人中最高的,所以他前面的和后面的必定是矮,,我们方案数划分为两部分,一部分是一高开头的方案数,一部分是以矮开头的方案数,这两部分是相等的(就相当于总的方案数等于其中的一个的2倍(注意1除外)),而以矮开头的,反过来就是以矮结尾的,所以以矮结尾的就等于以矮开头的,我们用dp[i][1]表示以矮开头的,用dp[i][0]表示以矮结束,由于不知道他前面和后面的人有多少个,所以要依次枚举,假设前面有j个人,那么他身后必定有i-j-1个人。那么总的方案数=dp[j][0]*dp[i-1][1]*c[i-1][j],c[i-1][j]表示从i-1个人中选j个人的方案数。
AC代码:
#include<stdio.h>
long long dp[22][2];
int c[22][22];
int main()
{
int i,j,p,q,n;
long long t;
for(i=1;i<=20;i++)
{
c[i][0]=c[i][i]=1;
for(j=1;j<i;j++)
{
c[i][j]=c[i-1][j-1]+c[i-1][j];//(杨辉三角的定理)
}
}
dp[1][0]=dp[1][1]=1;
for(i=2;i<=20;i++)
{
t=0;//t表示总的方案数
t+=dp[i-1][1]+dp[i-1][0];//这个表示第i个人排在最前面和最后面
for(j=1;j<i-1;j++)
{
t+=dp[j][0]*dp[i-j-1][1]*c[i-1][j];
}
dp[i][0]=dp[i][1]=t/2;
}
scanf("%d",&p);
while(p--)
{
scanf("%d%d",&q,&n);
if(n==1)//1除外
printf("%d %I64d\n",q,dp[1][0]);
else
printf("%d %I64d\n",q,dp[n][0]*2);
}
return 0;
}