问题描述
考虑数组arr
。
s1
和s2
是原始数组arr
的任意两个子集。我们应该对原始数组进行分区,以使这两个子集具有最小差异,即min(sum(s1) - sum(s2))
,其中sum(s1) >= sum(s2)
。
我应该打印这两个子集,即s1
和s2
作为我的输出。
您可以将这些子集存储在向量中。
例如,如果arr[] = [0,1,5,6]
,则最小差异为0
,而我的两个子集为s1[] = [0,5]
和 s2[] = [6]
。
另一个示例可能是arr[] = [16,14,13,12,10,9,3]
,两个子集分别是s1[]=[16,3]
和s2[] = [14,9]
,两者的最小差再次为0
。
我似乎无法弄清楚如何获得这两个子集。
非常感谢!
注意::我知道如何使用DP从两个子集中获得最小差异,但是我无法继续。它得到了我无法做到的两个子集(差异最小)。 只有沿着正确方向微移的算法才可以。
#include<iostream>
#include<vector>
using namespace std;
int min_subset_sum_diff(int a[],int n,int sum) {
vector<vector<bool>> go(n + 1,vector<bool>(sum + 1,false));
for (int i = 0; i < n + 1; ++i) {
go[i][0] = true;
}
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= sum; ++j) {
if (a[i - 1] <= j) {
go[i][j] = go[i - 1][j - a[i - 1]] || go[i - 1][j];
}
else {
go[i][j] = go[i - 1][j];
}
}
}
for (int j = (sum / 2); j >= 0; --j) {
if (go[n][j]) { // only need the last row as I need all the elements,which is n
return sum - 2 * j;
}
}
return INT_MAX;
}
int main() {
int a[] = { 3,100,4,4 };
int n = sizeof(a) / sizeof(a[0]);
int sum = 0;
for (auto i : a) {
sum += i;
}
cout << min_subset_sum_diff(a,n,sum);
}
s1 = sum(first_subset)
s2= sum(second_subset)
假设s2>=s1
,
s1 + s2 = sum_arr
s2 = sum_arr - s1 //using this in the next equation
s2-s1 = difference
(sum_arr - s1) - s1 = difference
sum_arr - 2*s1 = difference
这是我的基本逻辑。
sum(s1)
和sum(s2)
位于0..sum_arr
由于我假设s1 < s2
,所以s1的值只能在0..(sum_arr/2)
之间
我的目标是将sum_arr - 2*s1
的最小值设为最小,而对于最大的s1
则为真
解决方法
使整数T[][]
的并行表具有与go[][]
相同的维数
当您在此处做出决定
if (a[i - 1] <= j)
输入T[i][j]
的某种信息,指向true
的{{1}}前体坐标
填充表后,您将在布尔表的go[i][j]
行中搜索最佳的true
条目。找到后,从go[n]
表的同一单元格中获取值,并跟踪到前体,然后到前体,依此类推(“展开”子集信息)