uva10128(Queue)

来源:互联网 发布:mac照片占用空间 编辑:程序博客网 时间:2024/06/10 04:58

uva10128(Queue)
题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1069
题目描述:
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. Its 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
The input consists of T test cases. The number of them (1  T  10000) is given on the rst line of
the input le.
Each test case begins with a line containing a single integer number N that indicates the number
of people in a queue (1  N  13). Then follows line containing two integers. The rst integer
corresponds to the number of people, that we can see looking from the beginning. The second integer
corresponds to the number of people, that we can see looking from the end.
Output
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
Sample Output
90720
1026576
1

题意:有N个身高各异的人站成一排。如果某人比他左边所有的人都高,那么他可以往左看到整个队列以外,否则他的视线会被挡住;同样的,如果某人比他右边的人都高,那么他可以往右看到整个队列以外。
犯罪就在这里发生了。队列左边有一个人用回旋镖杀死了队列右边的一个人。此时恰有P个向左的视野没有被挡住,同时恰有R个向右的视野没有被挡住,这些人都可能是案件的目击证人。
辩护律师委托你算出这N个人有多少种可能的排列方法满足给定的P和R。1<=N<=13
分析:看到N的范围我就想到了有库函数中的排列函数,枚举每一个排列看是否符合条件,但是结果就是理所应当的超时。看了网上的分析,觉得好厉害,采用的是递推的方法(原文):假设现在队列由i-1个人变成了i个,由于谁后进到队列是无所谓的,不妨假设最矮的人是最后一个进入队列的,那么其所占的位置会有三种情况,第一种情况是站在队首,增加1个在前面能看到的人数,第二种情况是站在队尾,增加1个在后面能看到的人数,第三种情况是站在队伍中间,一共有i-2个位置可以站,但不会增加可见的人数。这样就能得到f[i][j][k]=f[i-1][j-1][k]+f[i][j][k-1]+(i-2)*f[i-1][j][k]。初始化f[1][1][1]=1。
代码:

#include<stdio.h>#include<string.h>#define MAXD 20int N, P, Q;long long int f[MAXD][MAXD][MAXD];void prepare(){    int i, j, k;    memset(f, 0, sizeof(f));    f[1][1][1] = 1;    for(i = 2; i <= 13; i ++)        for(j = 1; j <= i; j ++)            for(k = 1; k <= i; k ++)                f[i][j][k] = f[i - 1][j - 1][k] + f[i - 1][j][k - 1] + (i - 2) * f[i - 1][j][k];}int main(){    int t;    prepare();    scanf("%d", &t);    while(t --)    {        scanf("%d%d%d", &N, &P, &Q);        printf("%lld\n", f[N][P][Q]);    }    return 0;}
1 0
原创粉丝点击