安科 OJ 1054 排队买票 (递归,排列组合)

 

 

时间限制:1 sios

空间限制:128 M算法

题目描述

有M个小孩到公园玩,门票是1元。其中N个小孩带的钱为1元,K个小孩带的钱为2元。售票员没有零钱,问这些小孩共有多少种排队方法,使得售票员总能找得开零钱。注意:两个拿一元零钱的小孩,他们的位置互换,也算是一种新的排法。(M<=10)spa

输入

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

输出

输出一行,总的排队方案。blog

样例输入

4 2 2递归

样例输出

8队列

 

思路:思路挺简单的,先无论每一个小孩的不同,先算出来总共排列有多少种,再乘以 n 和 k 的阶乘就是答案了(乘以 n 和 k 的阶乘就是把 1 和 2 全排列),至于怎么算出来排列的种类,用递归算出来就能够了。ci

 

代码:io

 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:还有一种更快的算法,卡特兰数,百度出来的,呃,我也不太会,感兴趣的能够看下class

相关文章
相关标签/搜索