这道题有两种解法
首先上递归。可能疑惑点在fun(a-1,b)+fun(a,b-1)这段代码。我们试着推导一下把题目中的测试用例带入
fun(3,2)=fun(2,2)+fun(3,1)
=fun(1,2)+fun(2,1)+fun(2,1)+fun(3,0)
=0+fun(1,1)+fun(2,0)+fun(1,2)+fun(2,1)+fun(3,0)//题目中说了交换同一个需求的人交换位置是同一个排列所以fun(3,0)=1;fun(1,2)不能再分解,因为此时还鞋的小于租鞋的
=0+1+1+0+fun(1,1)+fun(2,0)+1
=0+1+1+0+1+1+1=5
根据推导可以明白这段代码的含义,一次固定一个位置然后下一次再固定一个 位置。递归到最深处,然后回溯,最后a=3,b=2,栈空
#include<stdio.h>
int fun(int a, int b){
if(a<b) return 0;//如果租鞋的少于还鞋的那么会导致无鞋可租,排列情况为0
if(b==0) return 1;//题目中说两个同样需求的人比如都是租鞋或都是还鞋交换位置是同一种排法,所以这里没人租鞋,就只有一种排列
return fun(a-1,b)+fun(a,b-1);
}
int main(void){
int m,n;
scanf("%d%d",&m,&n);//m还鞋 n租鞋
printf("%d\n",fun(m,n));
return 0;
}
然后递推
递推的想法比较简单,i表示还鞋,j表示租鞋,考虑只有还鞋的情况,设定dp[i][0]=1,只有租鞋的情况不成立所以不用考虑。
for循环里面的两个判断
if(i==j)租鞋的和还鞋的人数一样,当前位置只能考虑减少租鞋的人数。
if(i>j)还鞋的人数大于租鞋的人数,表明dp[i][j]既可以租鞋,也可以还鞋所以有借鞋,还鞋两种情况。
#include<stdio.h>
#include<string.h>
int dp[200][200];//dp[i][j]表示还鞋的有i个,租鞋的有j个
int main(void){
int m,n;
int i,j;
scanf("%d %d",&m,&n);
memset(dp,0,sizeof(dp));
for(i=1;i<=m;i++) dp[i][0]=1;
for(i=1;i<=m;i++){
for(j=1;j<=n;j++){
if(j==i) dp[i][j]=dp[i][j-1];//借鞋的不能超过还鞋的,所以这里是 j-1
if(i>j) dp[i][j]=dp[i][j-1]+dp[i-1][j];//还鞋的人数比租鞋的人多 ,当前位置放鞋借鞋都行
}
}
printf("%d\n",dp[m][n]);
return 0;
}