uva 10128 Queue (dp)

Queue

There is a queue with N people. Every person has a different heigth. We can see P people, when we are looking from the beginning, and R people, when we are looking from the end.It�s because they are having different height and they are covering each other. How many different permutations of our queue has such a interesting feature?

Input Specification

The input consists of T test cases. The number of them (1<=T<=10000) is given on the first line of the input file.

Each test case consists of a line containing three integer numbers: N that indicates the number of people in a queue (1 <= N <= 13), and then two more integers. The first corresponds to the number of people, that we can see looking from the beginning, and the second �corresponding to the number of people, that we can see looking from the end.

Output Specification

For every test case your program has to determine one integer. Print how many permutations of N people we can see exactly P people from the beginning, and R people, when we are looking from the end.

Sample Input

3

10 4 4

11 3 1

3 1 2

Output for the Sample Input

90720

1026576

1

 

容易想到从n个人推n+1个人的情况,开始想的是第n+1个放到队列里的是最高的,发现这样的话还是有太多种情况要考虑,没法写转移方程。假设放进去的是最矮的,那么这个最矮的就只用考虑3种情况了,队首,队末和队中。看来这种递推的问题,灵活的跳跃思维很重要啊。
#include<cstdio>
#include<map>
#include<queue>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#include<list>
#include<set>
#include<cmath>
using namespace std;
const int maxn = 10 + 5;
const long long INF = 1e12;
const double eps = 1e-6;
typedef unsigned long long ULL;
typedef long long LL;
typedef pair<int, int> P;
#define fi first
#define se second

LL dp[maxn][maxn][maxn];

void pre(){
    memset(dp, 0, sizeof dp);
    dp[1][1][1] = 1;
    for(int i = 1;i < 13;i++){
        for(int j = 1;j <= i;j++){
            for(int k = 1;k <= i;k++){
                dp[i+1][j+1][k] += dp[i][j][k];
                dp[i+1][j][k+1] += dp[i][j][k];
                dp[i+1][j][k] += (i-1)*dp[i][j][k];
            }
        }
    }
}

int main(){
    pre();
    int t;
    cin >> t;
    while(t--){
        int n, p, r;
        cin >> n >> p >> r;
        cout << dp[n][p][r] << endl;
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值