Skip to content

Latest commit

 

History

History

2809.Minimum-Time-to-Make-Array-Sum-At-Most-x

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 

2809.Minimum-Time-to-Make-Array-Sum-At-Most-x

首先我们要知道,我们不会给同一个位置的数字重复清零操作,因为后一次清零会完全浪费前一次清零。所以我们最多只会进行n次清零。

其次,这道题给人有一种错觉,使用清零次数与达成目标之间存在单调性的关系,即用的清零次数越多,就越容易实现sum<=x的目标。

我们先承认这种错觉。那么它会引导我们用二分搜值的思想,即给定清零次数T,我们是否能构造一种方案使得sum<=x呢? 我们想象一下,使用了T次清零之后,剩余的sum必然是这种形式

sum = {0 + nums2[a]*1 + nums2[b]*2 + ... + nums2[c] * (T-1)} +
       {nums1[x]+nums2[x]*T + nums1[y]+nums2[y]*T + .... nums1[z]+nums2[z]*T}

也就是说,我们需要将元素分为两部分,前一部分是apply了清零操作,后一部分是没有apply清零操作。显然,对于前一部分,为了使得sum最小,我们会按照nums2的数值倒序排列。对于后一部分,对于顺序没有要求。

那么我们该如何将元素进行最优的分割呢?暴力尝试的话需要2^n。有更好的方法吗?其实这可以考虑成01背包问题,我们将所有元素按照nums2升序排序:每个元素有“取”或者“不取”两种决策,求取T个元素时的最小代价。所以我们很容易定义dp[i][j]表示前i个元素里面清零j个元素的最小代价。

  1. 当清零第i个元素时,因为nums2值最大,第i个元素必然是最后一个被清零才合算。说明我们在前i-1个元素依然用了j-1次清零,第j次清零使得nums[i]以0进入代价,同时也让之前的i-1个元素多了一轮“回血”,故增加的代价是nums2[1:i-1]。
  2. 当不清零第i个元素时,说明第i个元素此时经历了j轮回血,故增加的代价是nums1[i]+nums2[i]*j

综上我们可以计算出任意的dp[i][j]. 通过dp[i][T]<=x就可以判断能否通过T次清零实现目标。

但是注意,本题里的单调性是不成立的。例如

[9,10,10,5,2,4]
[2,4,0,3,3,4]
40

这组数据。不清零已经符合条件。清零1次,反而结果最小只能是42了。有可能确实没有单调性。

事实上,一次DP已经解决所有的问题。我们只需寻找最小的j,使得dp[i][j]<=x即是答案。