contestDouble-58

181 阅读1分钟

1.删除字符使字符串变好 (简单模拟略)

2.检查操作是否合法 (枚举)

枚举给出坐标的八个方向,并判断是否符合要求。

3.K 次调整数组大小浪费的最小总空间 (区间dp)

首先明确一点,要求到浪费的最小值,那么这k次调整肯定是用得越多,最后产生的浪费越少。将题目转化一下:将一个数组分为k+1段,使得每段产生的浪费值之和最小。其中每一段的浪费值为,该段最大的数*该段长度-该段总元素和.

dp[i][j]:将nums中前i个元素分为j段的最小浪费空间和

dp[i][j] = min{dp[k - 1][j - 1] + k到i这一段的浪费值之和}其中0<=k<=i 其中当k==0时dp[i][j]=0到i这一段的浪费值。 为了减少时间复杂度,首先需要预处理出所有线段的浪费值,这需要n^2,然后再用上述的状态转移方程进行转移,最终的答案就为dp[n - 1][k + 1].

func minSpaceWastedKResizing(nums []int, k int) int {
   n := len(nums)
   g := make([][]int, n)
   for i := 0 ; i < len(g) ; i++ {
      g[i] = make([]int, n)
   }
   for i := 0 ; i < n ; i++ {
      maxVal := math.MinInt32
      sum := 0
      for j := i ; j < n ; j++ {
         sum += nums[j]
         if nums[j] > maxVal {
            maxVal = nums[j]
         }
         g[i][j] = maxVal * (j - i + 1) - sum
      }
   }
   dp := make([][]int, n)
   for i := 0 ; i < len(dp) ; i++ {
      dp[i] = make([]int, k + 2)
   }
   for i := 0 ; i < len(dp) ; i++ {
      for j := 0 ; j < len(dp[i]) ; j++ {
         dp[i][j] = math.MaxInt32
      }
   }
   for i := 0 ; i < n ; i++ {
      for j := 1 ; j < k + 2 ; j++ {
         for t := 0 ; t <= i ; t++ {
            if t == 0 {
               dp[i][j] = min(dp[i][j], g[t][i])
            } else {
               dp[i][j] = min(dp[i][j], dp[t - 1][j - 1] + g[t][i])
            }
         }
      }
   }
   return dp[n - 1][k + 1]
}

4.两个回文子字符串长度的最大乘积 (马拉车不想学)

这tm数据量就很离谱,必须用马拉车来做,普通dp过不了,不搞竞赛不想学这个玩意儿...