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. c语言贪心算法合并箭,LeetCode刷题题库:贪心算法
  2. Ubuntu 安装 Docker
  3. (转)SystemProcessesAndThreadsInformation
  4. python全栈开发内容_Python全栈开发之Day02
  5. python常用排序_python中的各种排序
  6. 蓝桥杯2015年第六届C/C++省赛A组第九题-垒骰子
  7. node-7.2.1 already installed, it's just not linked
  8. 多重继承有时候确实有必要
  9. msys2下用cmake构建poppler和libpng
  10. WordPress去掉分类链接中category目录的两种方法
  11. 热烈祝贺小明SEO博客网站正式上线
  12. Air应用:Splus微博,wing微博
  13. 基于H5的Speedtest网速测试工具搭建
  14. 操作系统总结(大全)
  15. 清华操作系统课程(向勇、陈渝)笔记——第三章(一)(计算机体系结构/内存分层体系)
  16. 大数至简,带您实现“数据自由”,炎凰数据免费社区版产品正式发布
  17. JDK配置(Win10, jdk1.8.0_181)
  18. 计算机在生态文明建设的改造,关于中国生态文明建设的现状与未来思考
  19. linux mint必装软件,Linux mint 系统实用软件推荐和安装
  20. OA开发的基本流程——写在开始

热门文章

  1. 神经网络图用什么软件做,如何绘制神经网络图
  2. 利用DirectX 11绘制的大致流程(天空盒示例)
  3. [Cesium] 使用primitive绘制多段线
  4. as3遍历对象所有属性的方法
  5. 动画片,喜洋洋与灰太狼
  6. Java毕业设计_数据结构课程在线学习辅导系统
  7. 马哥 mysql_马哥学习笔记十五——MySQL进阶之SQL语句
  8. jssdk分享设置_微信JSSDK分享页面自定义当前链接最简单示例
  9. php怎么调用类里面的方法_php调用类中的方法
  10. 物联网实训_Day01~Day06