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 <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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值