comments | difficulty | edit_url | rating | source | tags | ||
---|---|---|---|---|---|---|---|
true |
中等 |
2040 |
第 425 场周赛 Q3 |
|
给你一个整数数组 nums
和三个整数 k
、op1
和 op2
。
你可以对 nums
执行以下操作:
- 操作 1:选择一个下标
i
,将nums[i]
除以 2,并 向上取整 到最接近的整数。你最多可以执行此操作op1
次,并且每个下标最多只能执行一次。 - 操作 2:选择一个下标
i
,仅当nums[i]
大于或等于k
时,从nums[i]
中减去k
。你最多可以执行此操作op2
次,并且每个下标最多只能执行一次。
注意: 两种操作可以应用于同一下标,但每种操作最多只能应用一次。
返回在执行任意次数的操作后,nums
中所有元素的 最小 可能 和 。
示例 1:
输入: nums = [2,8,3,19,3], k = 3, op1 = 1, op2 = 1
输出: 23
解释:
- 对
nums[1] = 8
应用操作 2,使nums[1] = 5
。 - 对
nums[3] = 19
应用操作 1,使nums[3] = 10
。 - 结果数组变为
[2, 5, 3, 10, 3]
,在应用操作后具有最小可能和 23。
示例 2:
输入: nums = [2,4,3], k = 3, op1 = 2, op2 = 1
输出: 3
解释:
- 对
nums[0] = 2
应用操作 1,使nums[0] = 1
。 - 对
nums[1] = 4
应用操作 1,使nums[1] = 2
。 - 对
nums[2] = 3
应用操作 2,使nums[2] = 0
。 - 结果数组变为
[1, 2, 0]
,在应用操作后具有最小可能和 3。
提示:
1 <= nums.length <= 100
0 <= nums[i] <= 105
0 <= k <= 105
0 <= op1, op2 <= nums.length
为了方便描述,我们将题目给定的
接下来,定义
考虑
- 如果
$x$ 不使用操作 1 和操作 2,那么$f[i][j][k] = f[i-1][j][k] + x$ ; - 如果
$j \gt 0$ ,那么可以使用操作 1,此时$f[i][j][k] = \min(f[i][j][k], f[i-1][j-1][k] + \lceil \frac{x+1}{2} \rceil)$ ; - 如果
$k \gt 0$ 并且$x \geq d$ ,那么可以使用操作 2,此时$f[i][j][k] = \min(f[i][j][k], f[i-1][j][k-1] + (x - d))$ ; - 如果
$j \gt 0$ 并且$k \gt 0$ ,那么可以同时使用操作 1 和操作 2。如果先使用操作 1,那么$x$ 变为$\lceil \frac{x+1}{2} \rceil$ ,如果$x \geq d$ ,那么可以使用操作 2,此时$f[i][j][k] = \min(f[i][j][k], f[i-1][j-1][k-1] + \lceil \frac{x+1}{2} \rceil - d)$ ;如果先使用操作 2,那么$x$ 变为$x - d$ ,如果$x \geq d$ ,那么可以使用操作 1,此时$f[i][j][k] = \min(f[i][j][k], f[i-1][j-1][k-1] + \lceil \frac{x-d+1}{2} \rceil)$ 。
最终答案为
时间复杂度
class Solution:
def minArraySum(self, nums: List[int], d: int, op1: int, op2: int) -> int:
n = len(nums)
f = [[[inf] * (op2 + 1) for _ in range(op1 + 1)] for _ in range(n + 1)]
f[0][0][0] = 0
for i, x in enumerate(nums, 1):
for j in range(op1 + 1):
for k in range(op2 + 1):
f[i][j][k] = f[i - 1][j][k] + x
if j > 0:
f[i][j][k] = min(f[i][j][k], f[i - 1][j - 1][k] + (x + 1) // 2)
if k > 0 and x >= d:
f[i][j][k] = min(f[i][j][k], f[i - 1][j][k - 1] + (x - d))
if j > 0 and k > 0:
y = (x + 1) // 2
if y >= d:
f[i][j][k] = min(f[i][j][k], f[i - 1][j - 1][k - 1] + y - d)
if x >= d:
f[i][j][k] = min(
f[i][j][k], f[i - 1][j - 1][k - 1] + (x - d + 1) // 2
)
ans = inf
for j in range(op1 + 1):
for k in range(op2 + 1):
ans = min(ans, f[n][j][k])
return ans
class Solution {
public int minArraySum(int[] nums, int d, int op1, int op2) {
int n = nums.length;
int[][][] f = new int[n + 1][op1 + 1][op2 + 1];
final int inf = 1 << 29;
for (var g : f) {
for (var h : g) {
Arrays.fill(h, inf);
}
}
f[0][0][0] = 0;
for (int i = 1; i <= n; ++i) {
int x = nums[i - 1];
for (int j = 0; j <= op1; ++j) {
for (int k = 0; k <= op2; ++k) {
f[i][j][k] = f[i - 1][j][k] + x;
if (j > 0) {
f[i][j][k] = Math.min(f[i][j][k], f[i - 1][j - 1][k] + (x + 1) / 2);
}
if (k > 0 && x >= d) {
f[i][j][k] = Math.min(f[i][j][k], f[i - 1][j][k - 1] + (x - d));
}
if (j > 0 && k > 0) {
int y = (x + 1) / 2;
if (y >= d) {
f[i][j][k] = Math.min(f[i][j][k], f[i - 1][j - 1][k - 1] + (y - d));
}
if (x >= d) {
f[i][j][k]
= Math.min(f[i][j][k], f[i - 1][j - 1][k - 1] + (x - d + 1) / 2);
}
}
}
}
}
int ans = inf;
for (int j = 0; j <= op1; ++j) {
for (int k = 0; k <= op2; ++k) {
ans = Math.min(ans, f[n][j][k]);
}
}
return ans;
}
}
class Solution {
public:
int minArraySum(vector<int>& nums, int d, int op1, int op2) {
int n = nums.size();
int f[n + 1][op1 + 1][op2 + 1];
memset(f, 0x3f, sizeof f);
f[0][0][0] = 0;
for (int i = 1; i <= n; ++i) {
int x = nums[i - 1];
for (int j = 0; j <= op1; ++j) {
for (int k = 0; k <= op2; ++k) {
f[i][j][k] = f[i - 1][j][k] + x;
if (j > 0) {
f[i][j][k] = min(f[i][j][k], f[i - 1][j - 1][k] + (x + 1) / 2);
}
if (k > 0 && x >= d) {
f[i][j][k] = min(f[i][j][k], f[i - 1][j][k - 1] + (x - d));
}
if (j > 0 && k > 0) {
int y = (x + 1) / 2;
if (y >= d) {
f[i][j][k] = min(f[i][j][k], f[i - 1][j - 1][k - 1] + (y - d));
}
if (x >= d) {
f[i][j][k] = min(f[i][j][k], f[i - 1][j - 1][k - 1] + (x - d + 1) / 2);
}
}
}
}
}
int ans = INT_MAX;
for (int j = 0; j <= op1; ++j) {
for (int k = 0; k <= op2; ++k) {
ans = min(ans, f[n][j][k]);
}
}
return ans;
}
};
func minArraySum(nums []int, d int, op1 int, op2 int) int {
n := len(nums)
const inf = int(1e9)
f := make([][][]int, n+1)
for i := range f {
f[i] = make([][]int, op1+1)
for j := range f[i] {
f[i][j] = make([]int, op2+1)
for k := range f[i][j] {
f[i][j][k] = inf
}
}
}
f[0][0][0] = 0
for i := 1; i <= n; i++ {
x := nums[i-1]
for j := 0; j <= op1; j++ {
for k := 0; k <= op2; k++ {
f[i][j][k] = f[i-1][j][k] + x
if j > 0 {
f[i][j][k] = min(f[i][j][k], f[i-1][j-1][k]+(x+1)/2)
}
if k > 0 && x >= d {
f[i][j][k] = min(f[i][j][k], f[i-1][j][k-1]+(x-d))
}
if j > 0 && k > 0 {
y := (x + 1) / 2
if y >= d {
f[i][j][k] = min(f[i][j][k], f[i-1][j-1][k-1]+(y-d))
}
if x >= d {
f[i][j][k] = min(f[i][j][k], f[i-1][j-1][k-1]+(x-d+1)/2)
}
}
}
}
}
ans := inf
for j := 0; j <= op1; j++ {
for k := 0; k <= op2; k++ {
ans = min(ans, f[n][j][k])
}
}
return ans
}
function minArraySum(nums: number[], d: number, op1: number, op2: number): number {
const n = nums.length;
const inf = Number.MAX_SAFE_INTEGER;
const f: number[][][] = Array.from({ length: n + 1 }, () =>
Array.from({ length: op1 + 1 }, () => Array(op2 + 1).fill(inf)),
);
f[0][0][0] = 0;
for (let i = 1; i <= n; i++) {
const x = nums[i - 1];
for (let j = 0; j <= op1; j++) {
for (let k = 0; k <= op2; k++) {
f[i][j][k] = Math.min(f[i][j][k], f[i - 1][j][k] + x);
if (j > 0) {
f[i][j][k] = Math.min(f[i][j][k], f[i - 1][j - 1][k] + Math.floor((x + 1) / 2));
}
if (k > 0 && x >= d) {
f[i][j][k] = Math.min(f[i][j][k], f[i - 1][j][k - 1] + (x - d));
}
if (j > 0 && k > 0) {
const y = Math.floor((x + 1) / 2);
if (y >= d) {
f[i][j][k] = Math.min(f[i][j][k], f[i - 1][j - 1][k - 1] + (y - d));
}
if (x >= d) {
f[i][j][k] = Math.min(
f[i][j][k],
f[i - 1][j - 1][k - 1] + Math.floor((x - d + 1) / 2),
);
}
}
}
}
}
let ans = inf;
for (let j = 0; j <= op1; j++) {
for (let l = 0; l <= op2; l++) {
ans = Math.min(ans, f[n][j][l]);
}
}
return ans;
}