• 9.28栈、队列&状态压缩&双向搜索


    栈、队列

    有效括号

    可能左括号多,右括号少

    可能第一个出现的右括号和最后一个左括号不匹配

    可能没遇到左括号就遇到了右括号

    有效括号过程中最大栈长度

    遇到左括号,就在入栈期望遇到的对应右括号,并比较当前栈长度和最大长度,更新;

    遇到右括号,和栈顶元素判定一下,匹配的话就出栈并消掉,让栈长度--,不然就接着往后,什么也不做(实际上已经是非法括号序列了)

    滑动窗口最大值

    首先考虑窗口长度是否大于数组长度

    然后思路是确定窗口尾部的坐标(右),然后根据窗口长度确定窗口头的坐标

    队列中元素:遇到元素时,应先判别队列头的元素是否还合法,直到遇到合法的队头或全部清空

    合法的队头就意味着当前的窗口的最大值

    接着比较合法的窗口和当前元素,如果当前元素大于,就删掉这个元素(队尾)之前所有小于它的元素,直到遇到不小于它的

    如果当前元素小于,就入队列,因为之前元素会比现在先出队列,当前元素依然可以当最大值

    用双端队列就是因为队头可以出元素

    状态压缩

    将一个状态压缩为一个整数(通常为二进制数),就可以在更为方便地进行状态转移的同时,达到节约空间的目的。

    状态压缩是一种优化动态规划算法的技巧,用于降低空间复杂度。当动态规划问题的状态转移方程只涉及到相邻状态时,我们可以使用状态压缩技巧将二维的dp数组转化为一维,从而减少所需的空间。通过状态压缩,我们可以将空间复杂度从O(N^2)降低到O(N)。然而,需要注意的是,状态压缩可能会降低代码的可读性,特别是对于初次接触优化后的代码的人来说。

    动态规划算法的过程是随着阶段的增长,在每个状态维度上的分界点组成了DP拓展的轮廓。对于某些问题,我们需要在动态规划的状态中记录一个集合,保存这个轮廓的详细信息,以便于进行状态转移。若集合大小不超过 N ,集合中每个元素都是小于 k 的自然数,则我们可以把这个集合看做一个 N  位 k 进制数,以一个 [0,k^N-1] 之间的十进制整数的形式作为DP状态的一维。这种把集合转化为整数记录在DP状态中的一类算法被称之为状态压缩动态规划算法。
    就是说,原来是一组数(不大于n),每个格子存数据,如果这个数据不大于k(首先是要不超过10,即十进制内能表示),那就用长为n的数来记录它,相当于用一个数来表示了一组数,相当于一个字符串记录,要读某一个数,就读这个串的某一位

    常用为0,1即dp数组每位就记录01,那么就用一个数字来记录

    Eg:小国王

     从上一层分析就是说,保留上一层的信息,在第i层就有一些位置不能放,然后在此基础上放国王,使国王数量最多

    问题是,每层都最优,最后结果一定最优吗?

    只要任意王横坐标不相邻,就是合法状态;纵坐标不相邻,就是合法状态;

    综合就是横纵都不相邻

    让有国王的位置为1,没国王的位置为0,即状态为0100010 

    >>即右移,表示读取这个数的第i位,

    1. #include<iostream>
    2. #include<cstring>
    3. #include<algorithm>
    4. #include<vector>
    5. using namespace std;
    6. typedef long long LL;
    7. const int N = 12, M = 1 << 10, K = 110;
    8. int n, m;
    9. vector<int> state;
    10. int cnt[M]; //状态state[a]的国王个数
    11. vector<int> head[M];//head[i] 里存储在第i行状态为state[a]的情况下,上一行状态可以取到的合法状态statep[b]
    12. LL f[N][K][M]; //状态转移方程,存方案数
    13. bool check(int state)
    14. {
    15. for(int i = 0;i < n;i ++) //同一行两个国王不能相邻
    16. if((state >> i & 1) && (state >> i + 1 & 1))
    17. return false;
    18. return true;
    19. }
    20. int count(int state) //统计该状态下国王,即1的个数
    21. {
    22. int res = 0;
    23. for(int i = 0;i < n;i ++) res += state >> i & 1;
    24. return res;
    25. }
    26. int main()
    27. {
    28. cin >>n >> m;
    29. //预处理所有合法状态 (对于这两个状态压缩有疑惑的,看看上面的图)
    30. for(int i = 0;i < 1 << n;i ++)
    31. if(check(i))
    32. {
    33. state.push_back(i); //将合法方案存入state
    34. cnt[i] = count(i);
    35. }
    36. //预处理所有合法状态的合法转移
    37. for(int i = 0;i < state.size();i ++)
    38. for(int j = 0;j < state.size();j ++)
    39. {
    40. int a = state[i], b = state[j];
    41. if((a & b) == 0 && check(a | b)) //a & b 指第i行和i-1行不能在同列有国王, check(a|b) == 1 指i和i -1行不能相互攻击到
    42. head[i].push_back(j); //head[i] 里存储在第i行状态为state[a]的情况下,上一行状态可以取到的合法状态statep[b]
    43. }
    44. f[0][0][0] = 1; //求方案数时,初始方案需要为1,因为全部空 也是一种方案
    45. for(int i = 1;i <= n + 1;i ++) //枚举每一行
    46. for(int j = 0;j <= m;j ++) //国王数量
    47. for(int a = 0;a < state.size();a ++) //枚举合法方案
    48. for(int b : head[a])
    49. {
    50. int c = cnt[state[a]]; //状态state[a]的国王个数
    51. if(j >= c)
    52. f[i][j][state[a]] += f[i - 1][j - c][state[b]]; //f[i][state[a]], 在第i行状态为i时,所有i - 1行的状态数量
    53. //因为state[a]和a呈映射关系,所也可以写成
    54. // f[i][j][a] += f[i - 1][j - c][b];
    55. }
    56. cout << f[n + 1][m][0] << endl;//我们假设摆到n + 1行,并且另这一行状态为0,那么即得到我们想要的答案,
    57. //如果我们用f[n][m][]来获取答案,那么我们就要枚举最后一行的所有状态取最大值,来得到答案。

     例题: 最短Hamilton路径

    0-1,即有还是没有,等式右边是说前一个状态,w[k][j]就是由k到j的权值,前一个状态,k记录此时的终点,也是权值的起点。state表示走到这里时,一共走了哪些点,最终是要全为1,采用状态压缩,就要每访问到一个节点,就要把原数都往前移一位,并在最后添个1,表示又多访问了一个点等式左边 

    2704

    P能放,放了后周围的P就不能放。目的是在地图中p放最多

    暴力就是从头开始遍历,然后深搜,维护一个最大的炮兵数

    双向搜索

    3067

    就是给定一个数组,然后找一个子数组,让子数组可以被划分

    随便找两个数,然后在数组中找有没有这俩数的和,这是子数组有三个数的情况

    随便找两个数,然后再随便找两个数,四个数

    ……

    还是要递归去解决

    每个数有三种状态,

    1.不放入任何集合

    2.放入左边集合

    3.放入右边集合

    直接暴力就是从数组第一个开始往后,复杂度为3^n

    分两半,前一半放第一组的和为a,第二组放b,即a+b<=sum(n/2)

    后一半同理,有a+c=b+d,则有a-b=c-d,即转变成了每半自己的一个关系

    即统计每一半和为a-b的方案,

    一个数被放入第一组中,a−b的值变大,在第二组中,a−b的值变小,如果不放,则a−b不变,所以维护a−b的值即可。

  • 相关阅读:
    Python3: 列表(List) 2023-11-15
    【React】第三部分 组件实例的三大核心属性
    JVM之运行时数据区、内存结构、内存模型
    希尔排序(Shell Sort)
    C#学习记录——基本图形绘制
    Flutter 项目实战 高德定位计算距离并展示首页数据 (六)
    [MAUI]模仿网易云音乐黑胶唱片的交互实现
    AI音乐大模型时代:版权归属与创意产业的新生长点
    java计算机毕业设计校园共享单车系统源代码+系统+数据库+lw文档
    k8s kubernetes 1.23.6 + flannel公网环境安装
  • 原文地址:https://blog.csdn.net/m0_73553411/article/details/133376134