DP康复训练题

原题:洛谷P1990

核心:递推/DP

题源应该是铺地砖,所以采用一摸一样的思路,只是有两种不同的方块

我们先用最最简单的方式尝试一下枚举当最后一行被填满的情况:

1.如果我们只用第一种长方形的方块让最后一行填满,那就只有两种情况:

  A.最后一列刚好是一个竖着的砖头:     B.最后两列都是横着的砖头:

             

  那这个时候我们先定义一个数组F,F的意思取fill,F[i]表示刚好把第i列填满时有多少种方法

  这样的话,因为我们现在只用了第一种方块,所以只可以得出一部分递推公式:F[x]=F[x-1]+F[x-2]+······。这个省略号里的内容就应该是考虑第二种方块时候产生的总数。

2.那我们接着来考虑第二种方块填满最后一行时的情况:

  表面上看有两种:

     

  实际上这两个是一模一样的,他们只不过是取决于第n-1列那多出来的那一半是在哪里。所以,如果要使用第二种,最核心的问题是会出现一列有一半的情况。所以我们试着来表示一下这种只有一半的情况:

  再定义一个数组H,H的意思取half,H[i]表示把第i列填上一半有多少种方法

  我们再来想一想怎么样才能让这一行出现一半:一共有四种情况:

  A.在一个填满的列后面加上一个第二种方块:   B.在一个一半的列的空位上放一个横着的第一种方块:

             

  以及他们上下对称的另外两种情况。对B情况,为什么非要加在空位上呢?那如果加在凸起来的那一块上:

     

  我们最后需要的是每一列都被填满的情况,所以说上面的空位迟早要填,填的话又只能填第一种方块,所以如果在凸起来的那一块加的话是等效于先在③位置上先放一个,再往新形成的空位上再加上一个第一种方块,是属于按照情况B放之后出现的下一列的一种情况。所以说,H数组的真正完整的理解应该是:在第i-1列填满的情况下,让第i列只有一半有多少种方法。

  回到正题,接着来推H的递推式:

  情况A:取决于第i-1列有多少种填满的方式,而且凸出的那一块是可以在上也可以在下两种方式,所以总的是F[i-1]*2

  情况B:取决于第i-1列有多少种填一半的方式,但是当前这一块放的位置实际上取决于i-1列的空位在哪里,所以这种情况下是和上一个半行一一对应的,就是H[i-1]

  合起来:H[i]=F[i-1]*2+H[i-1]

  那么要怎么样把一个填了一半的在下一列变成一个完整的呢?(也就是从H[i]变到F[i+1])

  更简单,往空格那里塞一个第二种方块不就好了:

     这个图像好像有一点点眼熟?(x

  这样的话,在F[i]的推导式里空缺的一项就出来了:H[i-1]

那么把所有情况总结起来,得出最后的状态转移方程:

  F[i]=F[i-1]+F[i-2]+H[i-1]

  H[i]=F[i-2]*2+H[i-1]

还差一个初状态,画画图可以发现:

  F[1]=1(就竖着放一个),F[2]=2(横着放两个,竖着放两个)

  H[1]=0(随便怎么放第二个方块的凸块只能在第二列),H[2]=2(凸口在上\在下)

好了,结束。

AC代码:(就懒得打注释了)

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<algorithm>
  4. using namespace std;
  5. int F[10000010]={0},H[1000010]={0};
  6. int n;
  7. int _r(){
  8. int x=0;
  9. char c=getchar();
  10. while(c>'9'||c<'0')c=getchar();
  11. while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar();
  12. return x;
  13. }
  14. void DP(){
  15. F[1]=1;
  16. F[2]=2;
  17. H[2]=2;
  18. for(int i=3;i<=n;i++){
  19. F[i]=F[i-1]+F[i-2]+H[i-1];
  20. H[i]=2*F[i-2]+H[i-1];
  21. F[i]%=10000;
  22. H[i]%=10000;
  23. }
  24. }
  25. int main(){
  26. n=_r();
  27. DP();
  28. printf("%d",F[n]);
  29. return 0;
  30. }

  

  

题解 洛谷P1990 覆盖墙壁的更多相关文章

  1. 洛谷 P1990 覆盖墙壁

    P1990 覆盖墙壁 题目描述 你有一个长为N宽为2的墙壁,给你两种砖头:一个长2宽1,另一个是L型覆盖3个单元的砖头.如下图: 0 0 0 00 砖头可以旋转,两种砖头可以无限制提供.你的任务是计算 ...

  2. 题解-洛谷P4229 某位歌姬的故事

    题面 洛谷P4229 某位歌姬的故事 \(T\) 组测试数据.有 \(n\) 个音节,每个音节 \(h_i\in[1,A]\),还有 \(m\) 个限制 \((l_i,r_i,g_i)\) 表示 \( ...

  3. 题解 洛谷P5018【对称二叉树】(noip2018T4)

    \(noip2018\) \(T4\)题解 其实呢,我是觉得这题比\(T3\)水到不知道哪里去了 毕竟我比较菜,不大会\(dp\) 好了开始讲正事 这题其实考察的其实就是选手对D(大)F(法)S(师) ...

  4. 题解 洛谷 P3396 【哈希冲突】(根号分治)

    根号分治 前言 本题是一道讲解根号分治思想的论文题(然鹅我并没有找到论文),正 如论文中所说,根号算法--不仅是分块,根号分治利用的思想和分块像 似却又不同,某一篇洛谷日报中说过,分块算法实质上是一种 ...

  5. 题解-洛谷P5410 【模板】扩展 KMP(Z 函数)

    题面 洛谷P5410 [模板]扩展 KMP(Z 函数) 给定两个字符串 \(a,b\),要求出两个数组:\(b\) 的 \(z\) 函数数组 \(z\).\(b\) 与 \(a\) 的每一个后缀的 L ...

  6. 题解-洛谷P4724 【模板】三维凸包

    洛谷P4724 [模板]三维凸包 给出空间中 \(n\) 个点 \(p_i\),求凸包表面积. 数据范围:\(1\le n\le 2000\). 这篇题解因为是世界上最逊的人写的,所以也会有求凸包体积 ...

  7. 题解-洛谷P4859 已经没有什么好害怕的了

    洛谷P4859 已经没有什么好害怕的了 给定 \(n\) 和 \(k\),\(n\) 个糖果能量 \(a_i\) 和 \(n\) 个药片能量 \(b_i\),每个 \(a_i\) 和 \(b_i\) ...

  8. 题解-洛谷P5217 贫穷

    洛谷P5217 贫穷 给定长度为 \(n\) 的初始文本 \(s\),有 \(m\) 个如下操作: \(\texttt{I x c}\),在第 \(x\) 个字母后面插入一个 \(c\). \(\te ...

  9. 题解 洛谷 P2010 【回文日期】

    By:Soroak 洛谷博客 知识点:模拟+暴力枚举 思路:题目中有提到闰年然后很多人就认为,闰年是需要判断的其实,含有2月29号的回文串,前四位是一个闰年那么我们就可以直接进行暴力枚举 一些小细节: ...

随机推荐

  1. python之字符串方法upper/lower

    1.描述: upper():用于将字符串全部转换为大写字母 lower():用于将字符串全部转换为小写字母 2.语法 str.upper() str.lower() 3.返回值 upper()或low ...

  2. 鸟哥的linux私房菜——第六章学习(Linux文件与目录管理)

    ******************第六章学习****************** 1.[文件与目录管理] 在所有目录下面都会存在的两个目录,分别是 "." 与 "..& ...

  3. ysoserial Commons Collections2反序列化研究

    Apache Commons Collections2反序列化研究 环境准备 JDK 1.7 Commons Collections 4.0 javassit 前置知识 PriorityQueue() ...

  4. Open Source Web Monitor System

    Open Source Web Monitor System 开源 Web 监控系统 Front End Monitor System / Front End Monitor Platform 前端监 ...

  5. LeetCode 题解 593. Valid Square (Medium)

    LeetCode 题解 593. Valid Square (Medium) 判断给定的四个点,是否可以组成一个正方形 https://leetcode.com/problems/valid-squa ...

  6. 使用 js 实现十大排序算法: 插入排序

    使用 js 实现十大排序算法: 插入排序 插入排序 // 双重循环 refs xgqfrms 2012-2020 www.cnblogs.com 发布文章使用:只允许注册用户才可以访问!

  7. React-Native Tutorials

    React-Native Tutorials https://egghead.io/courses/react-native-fundamentals part free https://egghea ...

  8. c++ 读取ASCII

    void ReadASCII(BYTE* addr, size_t offset, char r[]) { size_t i = 0; char c; while (true) { c = *(add ...

  9. 21_MySQL表外连接实战

    -- 查询每名员工的编号.姓名.部门.月薪.工资等级.工龄.上司编号.上司姓名.上司部门? SELECT e.empno,#员工编号 e.ename,#员工姓名 e.deptno,#员工部门 e.sa ...

  10. STM32之SPI通信

    SPI总线简介 >SPI总线介绍 SPI接口是Motorola首先提出的全双工三线同步串行外围接口,采用主从模式(Master Slave)架构:支持多slave模式应用,一般仅支持单Maste ...