解题思路:
我们先考虑小朋友不交换的情况,仅仅考虑1 2 怎么排能正好找完钱,设1元为a,2元为b:
3a2b的情况下:设A=3 B=2
aaabb aabba aabab abaab ababa
而不能 abbaa·····
可以看出能排b在n+1个位置的时候只能是:
(a的数目-b的数目>=0)===>(A-剩下a的数目)-(B-剩下b的数目)>=0
所以这个条件要作为递归的一个退出条件。
当我们排列完了所有数字后,即可+1
OK
现在我们要解决一种情况(状态)下有多少种排列的问题 还是上面的例子 将1元替换成小写,2元为大写。
我们只需要考虑一种状态就行了 aaabb
abcAB abcBA
acb····· ·······BA
bac····· ·······BA
bca····· ·······BA
cab····· ·······BA
cba····· ·······BA
可以看出来 小写字母,按行看遵循的是A!,大写字母,按列看遵循的是B! 所以
一种状态下的所有排列p=A!*B!
根据以上理论我们可以编写我们的递归代码了
注意事项:
参考代码:
#include <iostream>
#include <math.h>
using namespace std;
int k=0,ONE,TWO,p;//ONE TWO 是1元 2元的人数 k(只考虑钱该怎么摆放,而不考虑交换的情况的"状态")
void fun(int n,int o,int t){//o为1元人数还剩多少 同理t为2元人数剩多少 n代表剩几个人
if(( (ONE-o)-(TWO-t) ) <0 )return;
if(n==0){
k+=p;
return;
}
if(o!=0)fun(n-1,o-1,t);
if(t!=0)fun(n-1,o,t-1);
}
int main(){
int one,two,n,
a=1,b=1;//a b 求阶乘 p为a*b 代表一种排队"状态"成功下,有p种排列
cin>>n>>one>>two;
ONE=one;TWO=two;
for(int i=0;i<one;i++)a*=(one-i);
for(int i=0;i<two;i++)b*=(two-i);
p=a*b;//一种状态下有多少种排列方式
fun(n,one,two);
cout<<k<<endl;
return 0;
}
0.0分
1 人评分
C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:
一点编程也不会写的:零基础C语言学练课程
解决困扰你多年的C语言疑难杂症特性的C语言进阶课程
从零到写出一个爬虫的Python编程课程
只会语法写不出代码?手把手带你写100个编程真题的编程百练课程
信息学奥赛或C++选手的 必学C++课程
蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程
手把手讲解近五年真题的蓝桥杯辅导课程
发表评论 取消回复