UVa1638 Pole Arrangement 递推

本文介绍了一种算法,用于计算特定条件下可见杆子的不同排列数量。通过从大到小放置杆子,并确保不会遮挡已放置的杆子,文章提供了一个递归公式并展示了一个C++实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

There are poles of height 1, 2, . . . , n in a row. If you look at these poles from the left side or the right
side, smaller poles are hidden by taller poles. For example, consider the two arrangements of 4 poles
in the next figure:
For each arrangement, only one pole can be seen from the left, and two poles can be seen from the
right.
You are to write a program to calculate the number of arrangements of n poles such that seen from
the left you see l poles and seen from the right you see r poles.
Input
Your program is to read from standard input. The input consists of T test cases. The number of test
cases T is given in the first line of the input. Each test case consists of a line containing three integers,
n, l, and r (1 ≤ l, r ≤ n ≤ 20), where n is the number of poles and l (resp. r) is the number of poles
that can be seen from the left (resp. right).
Output
Your program is to write to standard output. Print exactly one line for each test case. The line should
contain the number of arrangements of poles for the test case.
The following shows sample input and output for four test cases.
Sample Input
4
4 1 2
4 1 1
5 2 4
20 2 1
Sample Output
2
0
4

6402373705728000


这道题可以考虑从大到小安排杆子,这样的好处是,插入的杆子不会遮挡到已插入的杆子,

同时插如的杆子在最左端,则从左边可看到的杆子数加一;

在最右端,则从右边可看到的杆子数加一;

插入中间则无任何影响。

这样,我们可以得到递推式: a[i][j][k]=a[i-1][j-1][k]+a[i-1][j][k-1]+a[i-1][j][k]*(i-2);

其中j、k表示从左、右端所看见的杆子数。

需要注意的是n=20时,结果已超过int范围,故用long long 来存储


#include <iostream>
#include <cstdio>
#include <map>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <string>
using namespace std;
#define LL long long
LL a[25][25][25];
void p()
{
    memset(a,0,sizeof(a));
    a[1][1][1]=1;
        for(int i=2;i<=20;i++){
            for(int j=1;j<=20;j++){
                for(int k=1;k<=20;k++){
                    a[i][j][k]=a[i-1][j-1][k]+a[i-1][j][k-1]+a[i-1][j][k]*(i-2);
                }
            }
        }
}
int main()
{
    int t,n,l,r;
    p();
    scanf("%d",&t);
    while(t--){
        scanf("%d%d%d",&n,&l,&r);
        printf("%lld\n",a[n][l][r]);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值