解题思路:
    我们先考虑小朋友不交换的情况,仅仅考虑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.0分

1 人评分

C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:

一点编程也不会写的:零基础C语言学练课程

解决困扰你多年的C语言疑难杂症特性的C语言进阶课程

从零到写出一个爬虫的Python编程课程

只会语法写不出代码?手把手带你写100个编程真题的编程百练课程

信息学奥赛或C++选手的 必学C++课程

蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程

手把手讲解近五年真题的蓝桥杯辅导课程

评论列表 共有 0 条评论

暂无评论