08_Queue(队列UVa 10128)

本文深入探讨了如何使用动态规划解决特定队列排列问题,详细介绍了问题分析、状态转移方程以及实例应用,包括UVa1069和UVa10128题解。

问题描述:n(1<=n<=13)个身高均不相等的人站成一排,从左向右看能看见L个人,从右向左看能看见R个人,问这个队列有多少种排法?

问题分析:  1.n个人的身高可设为1~n,

       2.设dp[k][i][j]中,k代表当前有k个人的队列,i代表从左边看能看见的人数,j代表从右边看能看到的人数

       3.由于谁先进队列,谁后进队列无所谓,我们从最高的人开始排起,保证每次新加入队列的人都是队列里边最矮的一个。

       4.若将新加的人放在最左边,则dp[k][i][j] += dp[k-1][i-1][j];

          若将新加的人放在最右边,则dp[k][i][j] += dp[k-1][i][j-1];

          若将新加入的人放在中间的任意地方,则dp[k][i][j] += dp[k-1][i][j]*(k-2);

       所以状态转移方程为:dp[k][i][j] = dp[k-1][i-1][j] + dp[k-1][i][j-1] + dp[k-1][i][j]*(k-2);

例题链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1069

例题:UVa 10128

10128 - Queue

Time limit: 3.000 seconds

  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 file.

  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 first 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

代码:

 1 #include "stdio.h"
 2 #include "string.h"
 3 #define N 15
 4 int dp[N][N][N];
 5 
 6 int main()
 7 {
 8     int T;
 9     int n,L,R;
10     int i,j,k;
11     scanf("%d",&T);
12     memset(dp,0,sizeof(dp));
13     dp[1][1][1] = 1;
14     for(k=2; k<N; k++)
15     {
16         for(j=1; j<=k; j++)
17         {
18             for(i=1; i<=k-j+1; i++)
19                 dp[k][i][j] = dp[k-1][i][j]*(k-2) + dp[k-1][i-1][j] + dp[k-1][i][j-1];
20         }
21     }
22     while(T--)
23     {
24         scanf("%d %d %d",&n,&L,&R);
25         printf("%d\n",dp[n][L][R]);
26     }
27 }

 

转载于:https://www.cnblogs.com/ruo-yu/p/4387685.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值