UVa 1638 - Pole Arrangement(dp)

链接:

https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4513

 

题意:

有高为1, 2, 3,…, n的杆子各一根排成一行。从左边能看到L根,从右边能看到R根,求有多少种可能。

 

分析:

设d(i,j,k)表示让高度为1~i的杆子排成一行,从左边能看到j根,从右边能看到k根的方案数(设i≥2)。
按照从大到小的顺序安排各个杆子。假设已经安排完高度为2~i的杆子,
那么高度为1的杆子不管放哪里都不会挡住任何一根杆子。有如下3种情况。
情况1:插到最左边,则从左边能看到它,从右边看不见(因为i≥2)。
情况2:如果插到最右边,则从右边能看到它,从左边看不见。
情况3(有i-2个插入位置):插到中间,则不管从左边还是右边都看不见它。
在第一种情况下,高度为2~i的那些杆子必须满足:从左边能看到j-1根,从右边能看到k根,
因为只有这样,加上高度为1的杆子之后才是“从左边能看到j根,从右边能看到k根”。
虽然状态d(i,j,k)表示的是“让高度为1~i的杆子……”,而现在需要把高度为2~i+1的杆子排成一行,
但是不难发现:其实杆子的具体高度不会影响到结果,只要有i根高度各不相同的杆子,
从左从右看分别能看到j根和k根,方案数就是d(i,j,k)。换句话说,情况1对应的方案数是d(i-1,j-1,k)。
类似地,情况2对应的方案数是d(i-1,j,k-1),而情况3对应的方案数是d(i-1,j,k)*(i-2)。
这样,就得到了如下递推式:d(i,j,k) = d(i-1,j-1,k) + d(i-1,j,k-1) + d(i-1,j,k)*(i-2)。

 

代码:

 1 import java.io.*;
 2 import java.util.*;
 3 
 4 public class Main {
 5     static final int UP = 20 + 1;
 6     static long d[][][] = new long[UP][UP][UP];
 7     
 8     static void constant() {
 9         d[1][1][1] = 1;
10         for(int n = 2; n < UP; n++) {
11             for(int L = 1; L <= n; L++) {
12                 for(int R = 1; R <= n; R++) {
13                     d[n][L][R] += d[n-1][L-1][R];
14                     d[n][L][R] += d[n-1][L][R-1];
15                     d[n][L][R] += d[n-1][L][R] * (n-2);
16                 }
17             }
18         }
19     }
20     
21     public static void main(String args[]) {
22         Scanner cin = new Scanner(new BufferedInputStream(System.in));
23         constant();
24         
25         int T = cin.nextInt();
26         while(T --> 0) {
27             int n = cin.nextInt();
28             int L = cin.nextInt();
29             int R = cin.nextInt();
30             System.out.println(d[n][L][R]);
31         }
32         cin.close();
33     }
34 }

 

posted @ 2018-05-04 20:29  Ctfes  阅读(142)  评论(0编辑  收藏  举报