问题 1163: 【排队买票】
问题描述
有M个小孩到公园玩,门票是1元。其中N个小孩带的钱为1元,K个小孩带的钱为2元。售票员没有零钱,问这些小孩共有多少种排队方法,使得售票员总能找得开零钱。注意:两个拿一元零钱的小孩,他们的位置互换,也算是一种新的排法。(M<=10)
输入
输入一行,M,N,K(其中M=N+K,M<=10).
输出
输出一行,总的排队方案。
样例输入
4 2 2
样例输出
8
递归解决排列问题
先算出不交换相同零钱小孩时的情况数
再乘两个小孩数的阶乘
long int qk(int lq, int a1,int a2)
{
if(lq<0 ||(a1==0&&a2>lq)) //当在这个情况下无法满足条件
return 0;
if(a1==0||a2==0) //在除去上面情况外,这个情况满足条件,总数加一
return 1;
if(lq==0) //零钱为零只能存在下一个小孩拿一块的情况
return qk(lq+1,a1-1,a2);
return (qk(lq+1,a1-1,a2)+qk(lq-1,a1,a2-1)); //如果上面都不符合,即可以出现两种情况
}
参考代码
#include <iostream>
#include <stdio.h>
using namespace std;
long int qk(int lq,int a1,int a2);
long int jc(int n);
int main()
{
int m,a1,a2;
while(scanf("%d %d %d",&m,&a1,&a2)!=EOF)
{
long int s=0;
if(a1<a2)
cout << "0"<<endl;
else
{
s=qk(1,a1-1,a2);
s=jc(a1)*jc(a2)*s;
cout <<s<<endl;
}
}
return 0;
}
long int qk(int lq, int a1,int a2)
{
if(lq<0 ||(a1==0&&a2>lq))
return 0;
if(a1==0||a2==0)
return 1;
if(lq==0)
return qk(lq+1,a1-1,a2);
return (qk(lq+1,a1-1,a2)+qk(lq-1,a1,a2-1));
}
long int jc(int n)
{
int s=1;
for(int i=n;i>1;i--)
{
s*=i;
}
return s;
}