算法训练 未名湖边的烦恼

这道题有两种解法

首先上递归。可能疑惑点在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;
} 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值