关于未名湖边的烦恼问题

昨天,我很受伤,自尊心严重受损,一切的一切都来源于一道题——未名湖边的烦恼,这是蓝桥杯官网的一道题,我看到后一直没有思路,最后无奈之下,我去百度上找了一篇讲这个题的博客,轻轻松松的就找到了,然而它里面的一句话刺痛了我:在蓝桥杯官网看到这道题,很水的一道题……这还不是最打击我的,当我看到他的代码,只用了区区几行代码,虽然有些小问题,但是把核心问题解决了,因为代码太简洁,我甚至都没有看懂其中的个中缘由……感觉自己是弱鸡,弱爆了。我花了好大会儿菜看明白这个方法的思路。

不说了,说多了都是眼泪,让我们来具体分析这道题吧。题如下:

问题描述
 
每年冬天,北大未名湖上都是滑冰的好地方。北大体育组准备了许多冰鞋,可是人太多了,每天下午收工后,常常一双冰鞋都不剩。

每天早上,租鞋窗口都会排起长龙,假设有还鞋的m个,有需要租鞋的n个。现在的问题是,这些人有多少种排法,可以避免出现体育组没有冰鞋可租的尴尬场面。(两个同样需求的人(比如都是租鞋或都是还鞋)交换位置是同一种排法)

输入格式
  两个整数,表示m和n

输出格式
  一个整数,表示队伍的排法的方案数。

样例输入
3 2

样例输出
5

数据规模和约定
  m,n∈[0,18]
  
最初看到这个题,我在思考,如何去用递推解决,像二岔数列那样的解决方案,然而我一直想不开,也在纠结如何去除题上所说的重复的问题。当我看到代码时,我懵了,竟然用的是递归,我一直以为需要用递推才行,看来一开始思路就错了,那么剩下的都是无用功,南辕北辙,所以做题一定要先给自己定好方向,如果真的想不开,那就换个角度想想,正着不行,咱就试试反着推,递推不行,就想想递归……诸此等等,都是方法。然而道理是这么讲的,但是他的递归我竟然没看懂。首先,为了方便解说,代码如下:

#include <stdio.h>

int FangAn(int m,int n);

int main(int argc, const char * argv[])
{
    int m=0,n=0,s=0;
    scanf("%d%d",&m,&n);
    s=FangAn(m, n);
    printf("%d\n",s);
    return 0;
}

int FangAn(int m,int n)
{
    if (m<n)
    {
        return 0;
    }
    if (n==0)
    {
        return 1;
    }
    return FangAn(m-1, n)+FangAn(m, n-1);  //  起初,我并不能理解这部分
}

这个递归感觉代码好简单,只是我根本不了解其本质,经过我的几轮研究,我才初步了解。

当我遇见这种抽象的代码时,我习惯先实例化一个简单的数据去尝试解题。它的递归的部分真的很好,主题思想就是一点点把大问题缩小成小问题。最初我不懂,这部分’return FangAn(m-1, n)+FangAn(m, n-1);’代码究竟是何种思想,当我把样例的数据代入演算时,我懂了一丢丢。

例如:
FangAn(3,2)=FangAn(2,2)+FangAn(3,1)
=FangAn(1,2)+FangAn(2,1) + FangAn(2,1)+FangAn(3,0)
=0 + FangAn(1,1)+FangAn(2,0) + FangAn(1,1)+FangAn(2,0) + 1
=0 + FangAn(0,1)+FangAn(1,0) + 1 + FangAn(0,1)+FangAn(1,0) + 1 + 1
=0+0+1+1+0+1+1+1
=5

就这个破题,我初步想通了,就是一次固定一个位置,然后去固定下一个位置,以此类推,一直到所有的都固定好,即得到结果。

但是随之问题来了,第一个位置只能固定为一个还鞋子的人,那么这个递归就不能正着实现了,对了,不能正着实现,那么我们就反着实现,毕竟最后一个位置可以是还鞋子的,也可以是借鞋子的,那么这个题的思路就是从最后一个位置开始固定,逐次固定到第一个,当 m < n 时则返回0,当 n == 0 时则返回1,就这样递归,最终得到的是所有的可行的方案数。

就这样,这道题算是结束了,告了一段落……不容忽视的问题摆在我面前,想要快点进步,那我就必须多学习,只靠自己的聪明是无法解决所有问题的,需要大量的补充知识空洞,来让自己能更加灵活的运用自如……-_-#

  • 32
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 28
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值