给定大小为N且整数K的数组arr [] ,任务是通过将数组拆分为K个子集,以使每个子集仅包含唯一的数组元素,以使每个子集的最大元素和最小元素之间的差之和最小。
例子:
Input: arr[] = { 6, 3, 8, 1, 3, 1, 2, 2 }, K = 4
Output: 6
Explanation:
One of the optimal ways to split the array into K(= 4) subsets are { { 1, 2 }, { 2, 3 }, { 6, 8 }, { 1, 4 } }.
Sum of difference of maximum and minimum element present in each subset = { (2 – 1) + (3 – 2) + (8 – 6) + (3 – 1) } = 6.
Therefore, the required output is 6
Input: arr[] = { 2, 2, 1, 1 }, K = 1
Output: -1
方法:使用带位屏蔽的动态编程可以解决该问题。以下是递归关系:
mask: ith bit of mask checks if array element is already selected in a subset or not.
l: index of last element selected in a subset.
j: index of current element selected in a subset.
If count of set bits in mask mod (N / K) == 1:
dp[mask][l] = min(dp[mask][l], dp[mask ^ (1 << l)][j])
Otherwise,
dp[mask][j] = min(dp[mask][j], dp[mask ^ (1 << j)][l] + nums[l] – nums[j])
请按照以下步骤解决问题:
- 遍历mask的所有可能值,即[0,2 N – 1]
- 初始化一个数组,例如n_z_bits [] ,以存储已在子集中选择的元素的数量。
- 使用上面的递归关系并填充递归关系的所有可能的dp状态。
- 最后,从dp [(1 << N)-1]中打印最小的元素。
下面是上述方法的实现:
Python3
# Python program to implement
# the above approach
from itertools import permutations
from itertools import combinations
# Function to minimize the sum of
# difference between maximums and
# minimums of K subsets of an array
def MinimizeSum(nums, k):
# Stores count of elements
# in an array
n = len(nums)
# Base Case
if k == n:
return 0
# Initialize DP[][] array
dp = [[float("inf")] * n for _ in range(1 << n)]
# Sort the array
nums.sort()
# Mark i-th element
# as not selected
for i in range(n):
dp[1 << i][i] = 0
# Iterate over all possible
# values of mask
for mask in range(1 << n):
# Store count of set bits
# in mask
n_z_bits = []
# Store index of element which is
# already selected in a subset
for p, c in enumerate(bin(mask)):
if c == "1":
temp = len(bin(mask)) - p - 1
n_z_bits.append(temp)
# If count of set bits in mask
# mod (n // k) equal to 1
if len(n_z_bits) % (n//k) == 1:
for j, l in permutations(n_z_bits, 2):
temp = dp[mask ^ (1 << l)][j]
dp[mask][l] = min(dp[mask][l], temp)
else:
for j, l in combinations(n_z_bits, 2):
if nums[j] != nums[l]:
# Check if l-th element
# is already selected or not
mask_t = mask ^ (1 << l)
temp = (dp[mask_t][j] +
nums[j] - nums[l])
# Update dp[mask][l]
dp[mask][l] = min(dp[mask][l],
temp)
# Return minimum element
# from dp[(1 << N) - 1]
if min(dp[-1]) != float("inf"):
return min(dp[-1])
# If dp[-1] is inf then the
# partition is not possible
else:
return -1
# Driver Code
if __name__ == "__main__":
# Given array
arr = [ 6, 3, 8, 1, 3, 1, 2, 2 ]
K = 4
# Function call
print(MinimizeSum(arr, K))
6
时间复杂度: O(N * 2 N )
辅助空间: O(N * 2 N )