题目意思:
给一个n,求n个高矮不同的人排成一排使得高、矮依次排列的种数。
解题思路:
他只给了人数,我们假设所有人的身高从低到高排成一列,序号为1,2,3,4…
我们从前往后一个一个取,到了第n个人的时候,将这个人放入前n-1个人的序列中去,有n个位置可以放(也就是插空)。显然只有第n个人要插入的位置左边的人是由下降得到的(即他的身高小于他前一个人的身高),并且其右边的人的身高也是要小于他右边的人。只有这样才能将第n个人插进去(因为第n个人的身高在前n个人中是最高的)
dp[i][0] 就代表由i个人组成的满足第n个人所插位置左边序列的要求的情况种数。
dp[i][1] 就是另一条件的情况种数。
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll;
int p, n;
ll sum[30];
ll dp[30][2];
ll C(ll a, ll b)
{
ll res = 1;
if(a < b)
return 0;
for(int i = b + 1; i <= a; ++ i)
{
res *= i;
}
for(int i = 1; i <= a - b; ++ i)
{
res /= i;
}
return res;
}
int main()
{
dp[0][0] = dp[0][1] = 1;
dp[1][0] = dp[1][1] = 1;
sum[1] = 1;
for(int i = 2; i <= 20; ++ i)
{
sum[i] = 0;
for(int j = 1; j <= i; ++ j)
{
sum[i] += dp[j - 1][0] * dp[i - j][1] * C(i - 1, j - 1);
}
dp[i][0] = dp[i][1] = sum[i] / 2; //两种情况种数是一致的,不管i是奇数还是偶数
}
cin >> p;
while(p--)
{
int index;
cin >> index >> n;
cout << index << ' ' << sum[n] << endl;
}
return 0;
}