1. 程式人生 > >UVa 580 - Critical Mass(遞推)

UVa 580 - Critical Mass(遞推)

ext blank href lan page show break tar []

鏈接:

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

題意:

有一些裝有鈾(用U表示)和鉛(用L表示)的盒子,數量均足夠多。
要求把n(n≤30)個盒子放成一行,但至少有3個U放在一起,有多少種放法?
例如,n=4, 5時答案分別為3, 8。

分析:

設答案為f(n)。既然有3個U放在一起,可以根據“最左邊的3個U”的位置分類。假定是i、i+1和i+2這3個盒子,
則前i-1個盒子不能有3個U放在一起的情況。設n個盒子“沒有3個U放在一起”的方案數為g(n)=2^n-f(n),


則前i-1個盒子的方案有g(i-1)種。後面的n-i-2個盒子可以隨便選擇,有2^(n-i-2)種。
但是,即使前i-1個盒子內部不出現3個U,仍然可能和i、i+1和i+2組成3個U。
所以強制讓第i-1個盒子(如果存在)放L,則前i-2個盒子內部不能出現連續的3個U。
因此f(n)=2^(n-3) + sum( g(i-2) * 2^(n-i-2) ), 2≤i≤n-2。
邊界是f(0)=f(1)=f(2)=0。g(0)=1,g(1)=2,g(2)=4。註意上式中的2^(n-3)對應於i=1的情況。

代碼:

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

UVa 580 - Critical Mass(遞推)