【动态规划】矩形覆盖

1. 题目描述

假设我们可以用如图1所示21的小矩形横着或者竖着去覆盖更大的矩形,请问用8个21的小矩形去无重复的覆盖一个2*8的大矩形。总共有多少种方法。

2.算法分析

这道题出自《剑指offer》,也是一道考察动态规划的基础题。把覆盖28矩形的覆盖方法总数记为f(8).用第一个矩形去覆盖大矩形时,有两种选择,横放或者竖放。竖放时,右边有27的区域尚未被覆盖,那么剩下区域覆盖方法的总数为f(7)。第一个矩形横向的情况下,必须占用另外一个小矩形去覆盖左下角。因此右边还剩下2*6的区域尚未被覆盖,记为f(6)。因此可以得出关系, f(8) = f(7) + f(6)。显然我们也知道f(1)=1,f(2) = 2.可以写出代码:

3. 实现1

#include<iostream>
using namespace std;
int covercnt(int n);
int main()
{
    int n;
    cin >> n;
    cout << covercnt(n);
}
int covercnt(int n)
{
    if (n  <= 0) {
        return 0;
    } else if (n == 1) {
        return 1;
    } else if (n == 2) {
        return 2;
    }
    return covercnt(n - 1) + covercnt(n - 2);    
}

这种实现用递归实现,当输入的n值稍微大一点,那么递归调用层次会很深,执行起来特别慢。仔细分析这个执行过程我们发现,重复的计算实在是太多了,比如计算f(8),必须先计算f(7)和f(6),计算f(7)的时候又要计算一次f(6),计算的中间结果不能复用,那么我们可以改进一下,开一个数组来保存中间结果,当需要计算f(n)时,首先查询数组中是否已经计算过了f(n)的值,如果有,那么不必重复计算,直接用,如果没有,那么计算一次,把计算结果保存到数组中。这是第一种方法,这种方法的好处就是已空间换时间,坏处就是,当需要计算的n值很大时,会很耗空间,同时,用户输入的n值不能提前预估大小,因此不能确定需要的数组长度。第二种方法是,自底向上来计算,比如计算f(8)的时候,我们从f(1)、f(2)开始算起,有了f(1)、f(2)的值就好计算f(3)了,有了f(2)、f(3)就好计算f(4)了,依次类推,很快可以计算出f(8)来。且看算法实现2.

4. 实现2

int covercnt(int n)
{
   int a , b , tmp = 0;
   if (n <= 0) {
       return 0;
   } else if (n == 1) {
       return 1;
   } else if (n == 2) {
       return 2;
   }
   a = 1; // a = f(1)
   b = 2; // b = f(2)
   n -= 2; // 从3开始计算
   while (n) {
       tmp = a + b;
       a = b;
       b = tmp;
       n--;
   }
   return tmp;
}

这种算法是比较理想的算法

全部评论

相关推荐

不愿透露姓名的神秘牛友
07-11 11:24
大家还是用ai改吧,我心疼得要死,就当花钱买教训吧,人家直接拿完钱就跑路了
程序员小白条:简历修改700....神奇,又不是帮你面试,咋的,简历修改从双非变92了还是没实习变成有大厂实习了
点赞 评论 收藏
分享
不愿透露姓名的神秘牛友
06-21 11:33
昨天是学校最后一场招聘会,鼠鼠去参加了,全场只有一个招聘java的岗位,上来先做一份笔试题,做完后他拿张纸对答案,然后开始问简历上的问题,深圳小厂,6-8k(题目如下),后面还有两轮面试。然后我就在招聘现场逛呀逛,看到有公司招聘电商运营,给的比上年的小厂还多,鼠鼠就去了解了下,然后hr跟鼠鼠要了份简历,虽然我的简历上面全是求职Java开发相关的内容,但是hr还是鼓励我说没关系,她帮我把简历给老板看看,下周一会给我通知。招聘会结束后鼠鼠想了一段时间,也和朋友聊了聊,发现我可能是不太适合这个方向,然后就跟爸爸说回家了给我发条微信,我有些话想跟他说说。晚上爸爸到家了,跟我发了条微信,我立马跑出图书馆跟他打起了电话,这个通话长达一个小时,主要是跟爸爸坦白说我不想找这行了,是你的儿子太没用了,想试试其他行业。然后爸爸也跟我说了很多,说他从来没有希望我毕业后就赚大钱的想法,找不到就回家去,回家了再慢慢找,实在找不到就跟他干(帮别人装修房子,个体户),他也知道工作不好找,让我不要那么焦虑,然后就是聊一些家常琐事。对于后面的求职者呢我有点建议想提一下,就是如果招实习的时间或者秋招开始,而你的简历又很差的情况下,不要说等做好项目填充完简历之后再投,那样就太晚了,建议先把熟悉的项目写上简历,然后边投边面边完善,求职是一个人进步的过程,本来就比别人慢,等到一切都准备好后再投岂不是黄花菜都凉了。时间够的话还是建议敲一遍代码,因为那样能让你加深一下对项目的理解,上面那些说法只是针对时间不够的情况。当然,这些建议可能没啥用,因为我只是一个loser,这些全是建立在我理想的情况下,有没有用还需其他人现身说法。上篇帖子没想到学校被人认了出来,为了不丢脸只能匿名处理了。
KPLACE:找研发类或技术类,主要还是要1.多投 2.多做准备,很多方面都要做准备 3.要有心理准备,投累了就休息一两天,再继续,要相信自己能找到
投递58到家等公司7个岗位
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务