状压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;
}

  • 13
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
vue-puzzle是一个Vue.js的人机验证组件,它可以用于在前端实现拼图验证码功能。 该组件可以用于替代第三方SDK的拼图验证,避免了引入SDK和后台配合的麻烦。你只需要通过npm安装vue-puzzle-vcode即可开始使用。 使用vue-puzzle-vcode时,你需要在代码中引入Vcode组件并使用它来展示验证模态框。你可以设置show属性来控制模态框的显示与隐藏,通过onSuccess事件来处理用户通过验证后的逻辑,通过onClose事件来处理关闭模态框的逻辑。 在示例中,当用户点击登录按钮时,会触发onSubmit方法,使验证码模态框显示出来。当用户通过验证后,会触发onSuccess方法,你需要在该方法中手动隐藏模态框。当用户点击遮罩层时,会触发onClose方法,你需要在该方法中关闭模态框。 除了以上提到的参数外,vue-puzzle还提供了其他可配置的参数,你可以根据需求进行设置。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Vue拼图验证组件使用教程](https://blog.csdn.net/weixin_40121676/article/details/102895804)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [vue 使用vue-puzzle-vcode拼图验证纯前端实现](https://blog.csdn.net/qq_37816525/article/details/102560656)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

EQUINOX1

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值