The King’s Ups and Downs【dp,排列组合】

在题目中主要的思考是,如何确定第n个和前面的关系,我们首先考虑的是,n和前面n-1个的关系,我们在n个中将n个人从矮到高依次排序为1~n,而依照题意,我们在第i个位置插入n必须满足题目意思,又因为n为当前最高点,所以只能左边为高矮,右边为矮高,又因为在全部的排列组合中,只存在矮高和高矮的顺序,所以设dp[i][0]为高矮,dp[i][1]为矮高,dp[i][0]=dp[i][1]=sum[i]/2;又因为在前面j个为高矮的时候可以在总共的i个数中取i个,所以我们可以用排列组合的方法分析在i个中取前j个种类是多少 C(int i,int j);
综上所述,我们可以得到转移方程式:sum[i]+=(dp[j-1][0]*dp[i-j][1]*Cal(i-1,j-1));
代码如下:

#include<bits/stdc++.h>
using namespace std;
const double eps = 1e-5;
const double PI = acos(-1.0);
typedef long long ll;
ll dp[30][2];//dp[i][j]任意i个中排列为0状况的方法多少种
ll sum[30];//在第i个的时候有多少个方法
ll Cal(int a,int b)//a个中取b个的方法多少个,排列组合
{
    if(b==0)
        return 1;
    ll res=1;
    for(int i=0;i<b;i++)
        res*=(a-i);
    for(int i=1;i<=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++)//在前面放j-1个
            sum[i]+=(dp[j-1][0]*dp[i-j][1]*Cal(i-1,j-1));
        dp[i][0]=dp[i][1]=sum[i]/2;//由对称性
    }
    int t;
    int d,k;
    cin>>t;
    while(t--)
    {
        cin>>d>>k;
        cout<<d<<" "<<sum[k];
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值