题目大意:
有n个士兵,身高分别为1--n,问这n个士兵排成一种每个士兵比旁边的两个人都高或都矮的队列的种数。
解题思路:
动态规划问题。f[i][0]代表i个人的队列,这个队列的第一个人比第二个人矮的排列个数,f[i][1]代表i个人的队列,这个队列的最后一个人比倒数第二个人矮的排列个数。由对称性得f[i][0] == f[i][1],记i个人的排列个数为ans,则ans = (f[j][1]*f[i-j-1][0]*c(i-1,j)), 0 <= j < i。f[i][0] = ans/2,f[i][1] = ans/2。因为可以假设每次新加入的人的身高是最高的,第i个人可以放在0到i-1的任意位置。所以i的前面后后面分别有j个人和i-j-1个人,且前j个人的最后一个要比倒数第二个人矮,后i-j-1个人的第一个人要比第二个人要矮。前j个人可以在i-1个人中任选。
代码:
#include <iostream>
using namespace std;
long long c[25][25];
long long f[25][2];
int main()
{
int d,n,p;
for(int i = 1; i < 20; i ++){
c[i][0] = 1;
c[i][i] = 1;
for(int j = 1; j < i; j ++){
c[i][j] = c[i-1][j] + c[i-1][j-1];
}
}
f[0][0] = 1;
f[0][1] = 1;
f[1][0] = 1;
f[1][1] = 1;
for(int i = 2; i <= 20; i ++){
long long ans = 0;
for(int j = 0; j < i; j ++){
ans += f[j][1] * f[i-j-1][0] * c[i-1][j];
}
f[i][0] = ans/2;
f[i][1] = ans/2;
}
cin >> p;
for(int i = 0; i < p; i ++){
cin >> d >> n;
cout << d << " ";
if(n == 1) cout << 1 << endl;
else cout << 2*f[n][0] << endl;
}
return 0;
}