1. 程式人生 > >UVa 1638 - Pole Arrangement(dp)

UVa 1638 - Pole Arrangement(dp)

itemid 如果 發現 ++ system.in nbsp sca rgs com

鏈接:

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 }

UVa 1638 - Pole Arrangement(dp)