状压dp,D - Grid Puzzle

一、题目

1、题目描述

2、输入输出

2.1输入

2.2输出

3、原题链接

D - Grid Puzzle


二、解题报告

1、思路分析

贪心做法看不懂(为什么我赛时要跟贪心过不去啊)

这个题麻烦在这个case:2 4 4 2,我们可以清除三次2x2得到

但是我们始终有一个原则:相邻两行一定是两次操作以内完成的,不可能有3次清除2x2来清除相邻两行的存在,否则我们可以两次清行来替换

这也是为什么我一直死磕贪心,没写状压

其实状压的话就很经典了,比蒙德里安的理想要简单

我们考虑这样定义状态 f(i, j), j = 0, 1, 2, 3

f(i, 0):清除前i行,第i行清行(注意这个状态定义清行可以继承前面的2x2操作)

f(i, 1):清除前i行,第i行在1、2两个格子清空2x2(会对下一行有影响)

f(i, 2):清除前i行,第i行在3、4两个格子清空2x2(会对下一行有影响)

f(i, 3):清除前i行,第i行在1、2 | 3、4分别清空2x2(会对下一行有影响)

状态转移:

如果a[i] > 4 以及 不考虑前面2x2操作的情况下

f[i][0] = min(f[i - 1]) + 1

如果 a[i] <= 4,那么我们就要考虑2x2了:

          f[i + 1][0] =  min(f[i + 1][0], f[i][3]);
          f[i + 1][1] =  min(f[i + 1][1], f[i][2] + 1);
          f[i + 1][2] =  min(f[i + 1][2], f[i][1] + 1);
          f[i + 1][3] =  min(f[i + 1][3], f[i][0] + 2);

如果 a[i] <= 2:

          f[i + 1][0] =  min(f[i + 1][0], f[i][1]);
          f[i + 1][1] =  min(f[i + 1][1], f[i][0] + 1);

然后特判 a[i] == 0的情况,f[i][0] = min(f[i - 1])

2、复杂度

时间复杂度: O(4N)空间复杂度:O(4N)

3、代码详解

 ​
#include <bits/stdc++.h>
#define sc scanf
using i64 = long long;
using PII = std::pair<int, int>;
constexpr int inf32 = 1e9 + 7;
constexpr i64 inf64 = 1e18 + 7;

void chmin(int& x, int y) {
    x = y < x ? y : x;
}

void solve() {
    int n;
    std::cin >> n;
    std::vector<int> a(n);
    for (int i = 0; i < n; ++ i) std::cin >> a[i];

    std::vector<std::array<int, 4>> f(n + 1, { inf32, inf32, inf32, inf32 });
    
    f[0][0] = 0;

    for (int i = 0; i < n; ++ i) {
        f[i + 1][0] = *std::min_element(f[i].begin(), f[i].end()) + 1;
        if (a[i] <= 4) {
            chmin(f[i + 1][0], f[i][3]);
            chmin(f[i + 1][1], f[i][2] + 1);
            chmin(f[i + 1][2], f[i][1] + 1);
            chmin(f[i + 1][3], f[i][0] + 2);
        }
        if (a[i] <= 2) {
            chmin(f[i + 1][0], f[i][1]);
            chmin(f[i + 1][1], f[i][0] + 1);
        }
        if (a[i] == 0)
            chmin(f[i + 1][0], *std::min_element(f[i].begin(), f[i].end()));
    }

    std::cout << *std::min_element(f[n].begin(), f[n].end()) << '\n';
}

int main() {
#ifdef DEBUG
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
#endif
    std::ios::sync_with_stdio(false), std::cin.tie(nullptr), std::cout.tie(nullptr);
    int _ = 1;
    std::cin >> _;
    while (_ --)
        solve();
    return 0;
}

相关推荐

  1. 奖励关(概率dp+

    2024-07-21 07:36:01       18 阅读
  2. 【算法竞赛题目 & 题解收集】DP

    2024-07-21 07:36:01       44 阅读
  3. LeetCode 1349. 参加考试的最大学生数,DP

    2024-07-21 07:36:01       52 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-21 07:36:01       52 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-21 07:36:01       54 阅读
  3. 在Django里面运行非项目文件

    2024-07-21 07:36:01       45 阅读
  4. Python语言-面向对象

    2024-07-21 07:36:01       55 阅读

热门阅读

  1. SQL Server中的定制视野:实现数据库的自定义视图

    2024-07-21 07:36:01       18 阅读
  2. 【电子数据取证】了解数据库

    2024-07-21 07:36:01       16 阅读
  3. 软件设计模式: 抽象工厂

    2024-07-21 07:36:01       15 阅读
  4. js修改hash的方法

    2024-07-21 07:36:01       14 阅读
  5. 网页制作技术在未来会如何影响人们的生活?

    2024-07-21 07:36:01       15 阅读
  6. Vue学习(一)初识Vue、事件

    2024-07-21 07:36:01       15 阅读
  7. pcie_TLP

    pcie_TLP

    2024-07-21 07:36:01      14 阅读
  8. ChatGPT:SpringBoot 响应请求是串行还是并行?

    2024-07-21 07:36:01       13 阅读
  9. U425647题解

    2024-07-21 07:36:01       15 阅读
  10. .NET在游戏开发中有哪些成功的案例?

    2024-07-21 07:36:01       15 阅读
  11. vue和react中都使用的hook到底是什么?

    2024-07-21 07:36:01       16 阅读
  12. 如何理解李彦宏说的“不要卷模型,要卷应用”

    2024-07-21 07:36:01       16 阅读
  13. Markdown 链接

    2024-07-21 07:36:01       14 阅读
  14. 【算法】浅析贪心算法

    2024-07-21 07:36:01       15 阅读