The King’s Ups and Downs HDU - 4489(组合dp)

题目意思:

给一个n,求n个高矮不同的人排成一排使得高、矮依次排列的种数。

解题思路:
他只给了人数,我们假设所有人的身高从低到高排成一列,序号为1,2,3,4…
我们从前往后一个一个取,到了第n个人的时候,将这个人放入前n-1个人的序列中去,有n个位置可以放(也就是插空)。显然只有第n个人要插入的位置左边的人是由下降得到的(即他的身高小于他前一个人的身高),并且其右边的人的身高也是要小于他右边的人。只有这样才能将第n个人插进去(因为第n个人的身高在前n个人中是最高的)
dp[i][0] 就代表由i个人组成的满足第n个人所插位置左边序列的要求的情况种数。
dp[i][1] 就是另一条件的情况种数。

#include 
#include 
#include 

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;
}

你可能感兴趣的:(线性dp,dp)