问题描述
每年冬天,北大未名湖上都是滑冰的好地方。北大体育组准备了许多冰鞋,可是人太多了,每天下午收工后,常常一双冰鞋都不剩。
每天早上,租鞋窗口都会排起长龙,假设有还鞋的m个,有需要租鞋的n个。现在的问题是,这些人有多少种排法,可以避免出现体育组没有冰鞋可租的尴尬场面。(两个同样需求的人(比如都是租鞋或都是还鞋)交换位置是同一种排法)
输入格式
两个整数,表示m和n
输出格式
一个整数,表示队伍的排法的方案数。
样例输入
3 2
样例输出
5
数据规模和约定
m,n∈[0,18]
思路:
采用递归的方法简单易懂。
先要保证换鞋的人m多于借鞋的人n。否则,无论怎么排序,都是会出现无鞋可借的尴尬局面。
所以,首先判断(m>n),否则返回0,表示没有方法来排序。
之后,当还鞋的人数n为0 的时候,这时候无论怎么排序都是一种方法,所以这时候函数返回的是1;
这里的return fun(m-1,n)+fun(m,n-1)——前面的fun(m-1,n)意思是还鞋子的一个人站在最前面,之后剩下的人再接着排序,fun(m,n-1) 意思是借鞋子的人站在最后面,剩下的再接着排序。
代码呈上:
#include <stdio.h>
int fun(int n,int m)
{
if(n<m) return 0;
if(m==0) return 1;
return fun(n-1,m)+fun(n,m-1);
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
printf("%d\n",fun(n,m));
return 0;
}
运行示例
DP法:
dp[i][j] 表示当前有i个人还鞋,j个人借鞋时有多少种排法。需要注意的是,最开始先放还鞋的,并且在排的队列中当前位置之前借鞋的人数不能超过还鞋的人数,不然就借不到鞋了。
当i=j时,dp[i][j]=dp[i][j-1]
当i>j时,当前位置随便放借鞋还是还鞋都可以,
dp[i][j]=dp[i-1][j-1]+dp[i][j-1]
#include <stdio.h>
int main ()
{
int dp[20][20];
int m,n;
int i,j;
scanf("%d %d",&m,&n);
for(i=1;i<=m;i++)
{
dp[i][0]=1;
for(j=1;j<=n;j++)
{
if(i>j)
dp[i][j]=dp[i-1][j]+dp[i][j-1];
if(i==j)
dp[i][j]=dp[i][j-1];
}
}
printf("%d",dp[m][n]);
return 0;
}