当前位置:   article > 正文

2024/3/27打卡更小的数(十四届蓝桥杯)——区间DP

2024/3/27打卡更小的数(十四届蓝桥杯)——区间DP

目录

题目 

思路

代码


题目 

思路

        题目说求数组某个区间中的数进行翻转,由于区间选择多,首先想到DP问题。

        第一版想到的方法(错误的),当进行状态计算的时候,无法判定区间是否翻转后满足要求,即反转后的值小于翻转前的值。

        其二有个错误的点,对于包含 ij 的区间 [i,j] 进行翻转,只能被认定作为一个方案,无法从 i+1j-1 中传递过来,意思就是 [i,j] 区间中的区间进行翻转是与 [i,j] 无关的。

        看了别人的讲解后,恍然大悟。

        是一个区间动态规划问题,我们先枚举每个小区间,然后向大区间递增,大区间是否可以翻转满足要求,1.看是否右端点<左端点,2.如果右端点=左端点,看它比它小的一个区间是否可以翻转,可以,那么这个区间就可以。

        总结为:

  • a[l]>a[r]\ \ \ \ f[i][j]=1
  • a[l]=a[r] \&\&f[i+1][j-1]=1 \ \ \ f[i][j]=1
  • 其余情况不做处理

正确的DP分析: 

代码

  1. import java.io.*;
  2. class Main{
  3. static int N = 5010;
  4. static int n;
  5. static long res;
  6. static int[] a = new int[N];
  7. static int[][] f = new int[N][N];
  8. public static void main(String[] args) throws IOException{
  9. BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
  10. String s = in.readLine();
  11. n = s.length();
  12. for(int i=1;i<=n;i++) a[i] = Integer.parseInt(String.valueOf(s.charAt(i-1)));
  13. // 区间合并一般都先将小区间进行计算
  14. for(int len = 2;len<=n;len++){ // 枚举长度
  15. for(int i=1;i<=n;i++){ // 枚举左端点
  16. int j = i+len-1; // 右端点
  17. if(j>n) continue; // j<n
  18. if(a[j]<a[i]) f[i][j] = 1; //如果右端点小于左端点
  19. if(a[i]==a[j]&&f[i+1][j-1]==1) f[i][j] = 1; // 或者右端点等于左端点,但是左端点+1的数 > 右端点-1的数
  20. if(f[i][j]==1) res++; // 如果可以,res++
  21. }
  22. }
  23. System.out.println(res);
  24. }
  25. }
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/334383
推荐阅读
相关标签
  

闽ICP备14008679号