18121 排排坐看电影

18121 排排坐看电影

时间限制:1000MS  内存限制:65535K
提交次数:0 通过次数:0

题型: 编程题   语言: G++;GCC;VC

 

Description

某理工学校A班全为男生,另有某师范学校B班全为女生。一次,两个班组织了一次联谊活动,观看电影
《美人鱼》,订完票发现所有位置为同一排且从1到T号(T为人的总数),为了让参加活动的每一个女生都有机会同
男生有对话的机会,组织者在安排座位时,让女生左或右,至少有一个男生。现在告诉你男生人数n,女生
人数m,问一共有多少种不同的座位安排方法。




输入格式

每一行一个数W(W<=100),为case数量
此后W行,每行两个数n和m



输出格式

每个case输出一个结果(使用long long)



 

输入样例

7
3 0
3 1
0 1
1 1
2 2
2 3
2 4



 

输出样例

6
24
0
2
16
36
48



 

提示

注意:男生旁边可以没有女生



 

作者

 admin

  SCAU-排排坐看电影—递归。 有n个男生和m个女生,要求每个女生左边或右边至少有一个男生,而男生的位置则没有要求。利用递推的思想。假设下,按题目要求放置n个男生和m个女生的方法种数为recur(n,m); 一开始在一排位置的最边上,这个位置既可放男生又可放女生;如果放了男生,因为剩余有n个男生还未放置,所以会有n*recur(n-1,m)种的放法; 如果放了女生,同理,就是m*recur(n,m-1)种放法。 然后进入下一层递归,直至女生和男生都放完了或者遇到男生放完了但女生还有剩余数的无法进行下去的情况。

 那么,要如何判断当前的这个位置是否可以放女生或者男生女生皆可呢?  我的做法是在递归函数recur()里加多了两个参数:recur(n,m,p,pp);  其中p用来标记当前位置的前一个位置是女生还是男生;而pp就是用来标记 '前一个位置' 的前一个位置是男生还是女生;这样一来在函数里根据这两个参数就可以判定当前位置该如何放置了。  另外要注意的是函数递归的终止条件。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cstdlib>
 5 #include <cctype>
 6 #include <cmath>
 7 #include <algorithm>
 8 #include <set>
 9 #include <map>
10 #include <queue>
11 #include <stack>
12 #include <utility>
13 #include <vector>
14 #define ll long long
15 #define inf 0x3f3f3f3f
16 #define male 1    //用来标记男生和女生的常量
17 #define female 0
18 using namespace std;
19 
20 int A(int n) //计算n的阶乘
21 {
22     int ans=1;
23     for(int i=1; i<=n; i++)
24         ans*=i;
25     return ans;
26 }
27 ll recur(ll n,ll m,int p,int pp)
28 {
29     if(n>0&&m>0) //如果男生和女生都大于0
30     {
31         if(p==male) //如果当前位置的前一个人是男生,则该位置放男生或女生都可以
32             return m*recur(n,m-1,female,p)+n*recur(n-1,m,male,p);
33         else    //如果前一个位置是女生
34         {
35             if(pp==male) //且再前一个是男生,则该位置也是可以既放男生,或放女生
36                 return m*recur(n,m-1,female,p)+n*recur(n-1,m,male,p);
37             else        //当前一个和再前一个都是女生,则该位置一定要放男生; 形成'男女女男'的形式符合题目要求
38                 return n*recur(n-1,m,male,p);
39         }
40     }
41     else if(n>0) //如果女生没了,那剩下的n个男生可以形成n!种放法。
42     {
43         return A(n);
44     }
45     else if(m>0) //如果在考虑当前位置的时候已经是只剩女生了
46     {
47         if(p==male) //如果前一个位置为男生则在该位置放女生
48             return m*recur(n,m-1,female,p);
49         else  //如果前一个位置为女生则接下来的放置肯定是不符合题目要求的
50             return 0;
51     }
52     else if(!n&&!m) //所有人都放置完毕
53         return 1;
54 
55 }
56 int main()
57 {
58     //freopen("input.txt","r",stdin);
59     int w;
60     ll n,m;
61     ll ans;
62     scanf("%d",&w);
63     while(w--)
64     {
65         scanf("%lld%lld",&n,&m);
66         if(m>(n<<1)||!n) //如果 m>2n 或者n=0,就直接输出0
67         {
68             printf("0
");
69             continue;
70         }
71         ans=n*recur(n-1,m,male,-1)+m*recur(n,m-1,female,-1);
72         printf("%lld
",ans);
73     }
74     return 0;
75 }
原文地址:https://www.cnblogs.com/geek1116/p/5558679.html