LCP 38. 守卫城堡

题解给了两个解法,但是最小割我不太会,所以来写下我对dp解法对理解

题意

给你一个2∗N2*N2∗N的图,有城堡,怪物,障碍物,传送门,空地五种类型的物体。你每次可以放一次障碍物,问:至少需要放多少次才能把怪物跟城堡完全分隔开?

思路

一些不怎么显然的观察

讲道理看到图是2∗N2*N2∗N我想过用dp怎么做,但是想不到。这题的转移方式非常特别,我们来考虑怎么设计状态,因为有传送门,所以我们想到,怪物要么借助传送门走到城堡,要不不用传送门也能走到城堡。

  • 借助传送门走到城堡,如果有解,我们不允许怪物走到传送门。即可以把传送门当做城堡。
  • 不借助传送门走到城堡,如果有解,我们允许怪物走到传送门。即把传送门当作怪物

通过计算上面两个形态,我们就可以把传送门这一项给干掉了,所以我们只需要分别计算一下上面两种情况的最小值。

状态设计

so,下一步的问题变成了,我们需要在一张2∗N2*N2∗N的图中,添加最少的障碍物,把「怪物」和「城堡」分隔开。所以我们可以想象,一个「城堡」跟他周围的「空地」都属于同一个连通块,「恶魔」和「空地」周围的空地也属于同一个联通块。要完全分隔开如何做?

观察到有2行,4种物体,所以我们可以这么设计状态
f[i][a][b]f[i][a][b]f[i][a][b]表示当前考虑到了第iii列,第一个格子的状态为a, 第二个格子的状态为b,且将「怪物」同「城堡」分隔开的最小操作次数

a,b有四种状态,分别为

  • 0: 这个格子是个空地
  • 1:这个格子是个恶魔,或者之前恶魔可以到达的位置
  • 2: 这个格子是个城堡,或者之前城堡可以到达的位置。
  • 3: 这个格子是个障碍物

那么如何转移?在考虑第i列的所有状态时,我们来考虑第i-1列的所有状态。观察到「城堡」跟他周围的「空地」都属于同一个连通块这个条件,所以第i-1列的城堡会对当前列产生影响。比如,i-1列,第一个格子为「城堡」,而第i列第一个格子为「空地」时,我们不止可以更新「空地」这个状态,还可以更新「障碍物」这个状态(操作次数+1)。

最后枚举f[n][i][j]f[n][i][j]f[n][i][j]可以得到答案

题解参考

个人一些疑问

为什么这样可以从左到右考虑DP?当前考虑到第i列第时候,右边的恶魔不会对最小值产生影响吗?
那么对于我自己的问题,我大概有一个初步的想法,考虑到第i列第时候,我们只是把第i列左边的城堡跟恶魔全部分开的所有代价,后面的自然会在DP的时候考虑到。

代码

class Solution {public:int INF = 0x3f3f3f3f;int n, m;int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};int f[10010][4][4];vector<string> g;vector<string> change(vector<string>& grid, char c) {auto res = grid;for(int i = 0; i < 2; i++)for(int j = 0; j < m; j++)if(res[i][j] == 'P') res[i][j] = c;return res;}bool check() {for(int i = 0; i < n; i++) {for(int j = 0; j < m; j++) {for(int k = 0; k < 4; k++) {int a = i + dx[k], b = j + dy[k];if(a < 0 || a >= n || b < 0 || b >= m) continue;if(g[i][j] == 'S' && g[a][b] == 'C') return false;}}}return true;}void update(int i, int a, int b, int c, int d, int cost) {//a, c相邻,b, d相邻, 且互斥,直接返回。if(c == 1 || c == 2) {if(a + c == 3) return;//a可以被c改变if(!a) a = c;}if(d == 1 || d == 2) {if(d + b == 3) return;if(!b) b = d;}//改变之后冲突if((a == 1 || a == 2) && a + b == 3) return;//a跟b可以相互改变if((a == 1 || a == 2) && !b) b = a;if((b == 1 || b == 2) && !a) a = b;f[i][a][b] = min(f[i][a][b], f[i - 1][c][d] + cost);}int cal() {if(!check()) return INF;unordered_map<char,int> S = {{'.', 0}, {'S', 1}, {'C', 2}, {'#', 3}};memset(f, 0x3f, sizeof f);f[0][0][0] = 0;for(int i = 1; i <= m; i++) {int a = S[g[0][i - 1]], b = S[g[1][i - 1]];for(int c = 0; c < 4; c++) for(int d = 0; d < 4; d++) {update(i, a, b, c, d, 0);if(!a) update(i, 3, b, c, d, 1);if(!b) update(i, a, 3, c, d, 1);if(!a && !b) update(i, 3, 3, c, d, 2);} }int res = INF;for(int i = 0; i < 4; i++)for(int j = 0; j < 4; j++)res = min(res, f[m][i][j]);return res;}int guardCastle(vector<string>& grid) {n = 2, m = grid[0].size();int res = INF;g = change(grid, 'S');res = min(res, cal());g = change(grid, 'C');res = min(res, cal());if(res == INF) res = -1;return res;}
};

leetcode杯 LCP 38. 守卫城堡相关推荐

  1. 力扣第三题java_LeetCode 题解 | 力扣杯 LCP 06. 拿硬币

    力扣杯 LCP 06. 拿硬币(点击查看题目) 力扣​leetcode-cn.com 题目描述 桌上有 n 堆力扣币,每堆的数量保存在数组 coins 中.我们每次可以选择任意一堆,拿走其中的一枚或者 ...

  2. LeetCode Algorithm LCP 44. 开幕式焰火

    LCP 44. 开幕式焰火 Ideas 树类型的题目一般都需要用到递归,这道题相对来说比较简单,我们只需要遍历整棵树,然后把节点值记录到一个集合中,最后返回集合的长度就可以了. 所以这道题的考点就是树 ...

  3. 蓝桥杯, 38线译码器74Hc138

    38线译码器74hc138,具有三个地址输入(P2的高3位),八个输出,且输出为低电平 真值表为(图片为转载) 电路图为 我们可以用74hc138来选通74hc573,而74hc573控制数码管(段选 ...

  4. 【LeetCode】LCP 17. 速算机器人(C++)

    LCP 17. 速算机器人 1 题目描述 2 示例描述 2.1 示例1 3 解题提示 4 解题思路 5 代码详解 1 题目描述 小扣在秋日市集发现了一款速算机器人.店家对机器人说出两个数字(记作 x ...

  5. 【力扣-LeetCode】LCP 07. 传递信息 C++题解

    LCP 07. 传递信息 难度简单248收藏分享切换为英文接收动态反馈 小朋友 A 在和 ta 的小伙伴们玩传信息游戏,游戏规则如下: 有 n 名玩家,所有玩家编号分别为 0 - n-1,其中小朋友 ...

  6. 【Leetcode】 LCP 18. 早餐组合(简单)

    1. 题目 小扣在秋日市集选择了一家早餐摊位,一维整型数组 staple 中记录了每种主食的价格,一维整型数组 drinks 中记录了每种饮料的价格.小扣的计划选择一份主食和一款饮料,且花费不超过 x ...

  7. Leetcode杯 第三题解答(动态规划)

    最长重复字符子串 最常规的动态规划里有道题是在两个不同的字符串里找到最长的字符子串.而这次把题目稍稍改了下,不再是不同的字符串而是同一条字符串里找最长的字符子串,可以用同样的方法来解答.在交卷的一刹那 ...

  8. C#刷遍Leetcode面试题系列连载(2): No.38 - 报数

    前言 前文传送门: 上篇文章中我们主要科普了刷 LeetCode 对大家的作用,今天咱们就正式进行 LeetCode 算法题分析.很多人都知道计算机中有种思想叫 递归,相应地也出现了很多算法.解决递归 ...

  9. leetcode周赛,希望咸鱼,有一天可以薅到羊毛

    进阶指南每日一题地址 atcoder训练地址 leetcode max ratings:2100 碎碎念念 22/4/16 LCP春季杯 LCP 54. 夺回据点 少了个特判...qwq 22/3/6 ...

最新文章

  1. 刚毕业就能拿到56万年薪?对!看看Twitter机器学习大牛写给你的进阶手册吧
  2. 嵌入式系统实验 构建嵌入式Linux系统,《嵌入式系统与开发》构建嵌入式Linux系统-实验报告.doc...
  3. mkl gt;=2018
  4. 【django】模板(templates)
  5. Android 7.0 Keyguard流程分析
  6. xampp打开mysql的admin访问被拒绝_U盘插入电脑提示无法访问?别怕,我找到解决办法了...
  7. C语言重新定位文件,C语言代码重定位 (原创)
  8. 20应用统计考研复试要点(part1)--统计学
  9. [Leedcode][JAVA][第16题][最接近的三数之和][双指针][数组]
  10. FB宣布将回购60亿美元股票 首席会计官将离职
  11. markdown使用markdown-viewer生成目录_谷歌浏览器查看m文件
  12. 什么是redis缓存穿透, 缓存雪崩, 缓存击穿
  13. Springboot之添加本地模块依赖
  14. no such file or directory : 'users/shikx/xxx/xxx/Appirater.m'
  15. ca盘显示无证书_ca证书提示没有正确的安装驱动程序
  16. 微信小程序--对接萤石云视频监控
  17. 网易2016招聘笔试升级之路Java代码
  18. 红米ac2100有ipv6吗_红米AC2100刷padavan
  19. Cadence Allegro BGA扇出设置
  20. linux 看不到光盘刻录的文件夹,ARM_Linux下光盘刻录方案

热门文章

  1. 【插件】打造属于自己的cnpm/npm安装,生成自定义项目架构
  2. 数据结构(线性表,队列,栈,树,图)
  3. 【调剂】河北大学2020年硕士研究生拟接收调剂专业公告
  4. 长尾分布系列论文解析(一)Decoupling Representation and Classifier for Long-Tailed Recognition
  5. 电子钢琴C语言报告,【C语言】【windows】--电子钢琴
  6. 在WPS演示中如何将文本内容设置为环形?
  7. 英语语法自学网站 -------- 英语语法网
  8. 动态管理视图和动态管理函数学习
  9. 专升本计算机院校排名,计算机专接本学校2016排名
  10. 如何查看计算机系统管理日志,怎么查看电脑系统日志