- The King’s Ups and Downs

The king has guards of all different heights. Rather than line them up in increasing or decreasing height order, he wants to line them up so each guard is either shorter than the guards next to him or taller than the guards next to him (so the heights go up and down along the line). For example, seven guards of heights 160, 162, 164, 166, 168, 170 and 172 cm. could be arranged as: 


or perhaps: 


The king wants to know how many guards he needs so he can have a different up and down order at each changing of the guard for rest of his reign. To be able to do this, he needs to know for a given number of guards, n, how many different up and down orders there are: 

For example, if there are four guards: 1, 2, 3,4 can be arrange as: 

1324, 2143, 3142, 2314, 3412, 4231, 4132, 2413, 3241, 1423 

For this problem, you will write a program that takes as input a positive integer n, the number of guards and returns the number of up and down orders for n guards of differing heights. 

InputThe first line of input contains a single integer P, (1 <= P <= 1000), which is the number of data sets that follow. Each data set consists of single line of input containing two integers. The first integer, D is the data set number. The second integer, n (1 <= n <= 20), is the number of guards of differing heights. 
OutputFor each data set there is one line of output. It contains the data set number (D) followed by a single space, followed by the number of up and down orders for the n guards. 
Sample Input

4
1 1
2 3
3 4
4 20

Sample Output

1 1
2 4
3 10
4 740742376475050
题目大意:一组数据按照 “高低高低高低高低..”或者“底高低高低...”排列,数据的大小代表高低,
思路 : 这个题目难得很啊!!! 假设数据 n 将数据n放在中间那么从中间向左边读过去就是 高(n)低高低高低....。。从中间向右边读过去也是高(n)低高低....因此总的排列数就是 左边 的排列数 乘上 右边 的排列数、我们先固定好最大的那个数,然后从n-1个数中抽取j个数放在n的左边
根据排列组合就是  C(n-1,j);  dp[j][0]*dp[n-1-1][1]*C(n-1,j) 其中dp[j][0]是n左边J个人的排列总数dp[n-1-j][1]是n右边n-1-j个人的排列总数。然后再考虑最高的那个数的位置,,最后在连加就可以了。
AC代码:
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
ll sum[21];
ll dp[21][2];
ll c[21][21];
void cinin(){//这个函数是对排列组合数据的计算就是c(i,j)
for(int i=0;i<=21;i++){ c[i][0]=c[i][i]=1; } c[1][1]=1; for(int i=2;i<=21;i++){ for(int j=1;j<i;j++){ c[i][j]=c[i-1][j-1]+c[i-1][j]; } } } void solve(){ dp[0][0]=1;//左边为0个时为1(不可以为0,因为下边要做乘法) dp[1][0]=1;//左边1个数是为1 dp[1][1]=1;//右边同里 dp[0][1]=1; for(int i=2;i<=21;i++)//打表,一共20个人,,到21 这里就够了。 { ll s=0; for(int j=0;j<i;j++){//可以看成最高的数据所放的位置 s+=dp[j][0]*dp[i-j-1][1]*c[i-1][j]; } sum[i]=s; dp[i][0]=dp[i][1]=s/2;//把 i个人放在左边与把i个人放在右边应该相等并且总和是s(我也不太懂,以后再补吧) } return ; } int main(){ cinin(); sum[0]=0; sum[1]=1; solve(); int t; cin>>t; while(t--){ int a,b; cin>>a>>b; printf("%d %lld\n",a,sum[b]); } return 0; }

猜你喜欢

转载自www.cnblogs.com/Accepting/p/11272214.html