安科 OJ 1054 排隊買票 (遞迴,排列組合)
阿新 • • 發佈:2019-06-23
時間限制:1 s
空間限制:128 M
題目描述
有M個小孩到公園玩,門票是1元。其中N個小孩帶的錢為1元,K個小孩帶的錢為2元。售票員沒有零錢,問這些小孩共有多少種排隊方法,使得售票員總能找得開零錢。注意:兩個拿一元零錢的小孩,他們的位置互換,也算是一種新的排法。(M<=10)
輸入
輸入一行,M,N,K(其中M=N+K,M<=10).
輸出
輸出一行,總的排隊方案。
樣例輸入
4 2 2
樣例輸出
8
思路:思路挺簡單的,先不管每個小孩的不一樣,先算出來總共排列有多少種,再乘以 n 和 k 的階乘就是答案了(乘以 n 和 k 的階乘就是把 1 和 2 全排列),至於怎麼算出來排列的種類,用遞迴算出來就可以了。
程式碼:
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:還有一種更快的演算法,卡特蘭數,百度出來的,呃,我也不太會,感興趣的可以