1. 程式人生 > >安科 OJ 1054 排隊買票 (遞迴,排列組合)

安科 OJ 1054 排隊買票 (遞迴,排列組合)

 

 

有M個小孩到公園玩,門票是1元。其中N個小孩帶的錢為1元,K個小孩帶的錢為2元。售票員沒有零錢,問這些小孩共有多少種排隊方法,使得售票員總能找得開零錢。注意:兩個拿一元零錢的小孩,他們的位置互換,也算是一種新的排法。(M<=10)

輸入一行,M,N,K(其中M=N+K,M<=10).

輸出一行,總的排隊方案。

 1 #include <iostream>
 2 #include <cstdio>
 3 
 4 using namespace std;
 5 int m, n, k, sum;
 6 
 7 int fun(int ye, int nn, int kk)  // ye表示餘額,nn表示1元小孩人數,kk表示2元剩餘人數 
 8 {
 9     if(ye < 0)  return 0;        //餘額小於零,佇列無效 
10     if(!nn && !kk)  return 1;    //某個量排完,剩餘位置只能排剩餘的種類,因為這裡n >= k 
11                                  //保證剩下的排列合法,不會出現如:1 1 2 2 2 2 2 這種不合法的情況 
12     if(!ye)  return fun(ye + 1, nn - 1, kk);  //餘額為零,所以下一位只能排1元的位置 
13     return (fun(ye + 1, nn - 1, kk) + fun(ye - 1, nn, kk - 1));  //每次每個位置能排 1 和 2 兩種型別的位置 
14 } 
15 int main()
16 {
17     cin >> m >> n >> k;
18     if(n < k)  cout << "0";  //1的數量比2少的話不可能出現合法序列 
19     else
20     {
21         sum = fun(1, n - 1, k);  //保證第一位一定排1,不然佇列不合法 
22         int x1, x2;
23         x1 = x2 = 1;
24         for(int i = 1; i <= n; i ++ )   x1 *= i;
25         
26         for(int i = 1; i <= k; i ++ )   x2 *= i;
27         
28         sum = sum * x1 * x2;
29         cout << sum;
30     }
31     return 0;
32 }

 

PS:還有一種更快的演算法,卡特蘭數,百度出來的,呃,我也不太會,感興趣的可以