2

问题是打印总和为一个值的所有子集。我编写了代码来检查是否存在可能的子集。有人能给我一个想法来打印构成总和的数字吗?下面是我的代码。为简单起见,假设数组仅包含 +ve nos。

void subsetsum(int A[], int target) {

int N = sizeof(A)/sizeof(int), sum = 0;

for(int i = 0; i < N; i++) sum += A[i];

vector<bool> V(sum + 1, 0);
V[0] = 1;
for(int i = 0; i < N; i++) 
   for(int j = sum; j >= 0; j--) {
      if(j + A[i] <= sum && V[j]) V[A[i] + j] = 1;
   }
  if(V[target]) cout << "Sumbset sum exists" << endl;
  else cout << "Sumbset sum doesnt exist" << endl;
}
4

4 回答 4

3

首先,您需要生成所有子集

如果给定数组 [a,b,c,d],请考虑生成子集,一次从数组中获取每个元素。

子集(X)包括 y =foreach x in X append y to x

取a,我们得到subsets(a) = { [], [a] }

取b,我们得到子集(a,b)=子集(a)+(子集(a)包括b)

= { [], [a] } + { [b], [a,b] } = { [], [a], [b], [a,b] }

取 c,subsets(a,b,c) = subsets(a,b) + (subsets(a,b) 包括 c)

= {[], [a],[b],[a,b]} + {[c], [a,c], [b,c], [a,b,c]}

获得所有子集后,打印总和等于目标的子集。如果您不需要任何子集,您可以进一步修改上述算法。

于 2013-10-07T22:18:23.750 回答
1

求幂集的函数vector<int>

vector<vector<int>> power_set(const vector<int>& nums) {
  if (nums.empty()) { return { {} }; }
  auto set = power_set(vector<int>(begin(nums) +1, end(nums)));
  auto tmp = set;
  for (auto& p : tmp) {
    p.push_back(nums[0]);
  }
  set.insert(end(set), begin(tmp), end(tmp));
  return set;
}

返回总和为目标的幂集中所有集合的函数

vector<vector<int>> test_sum(const vector<vector<int>>& ps, int target) {
  vector<vector<int>> v;
  for (auto& p : ps) {
    int sum = accumulate(begin(p), end(p), 0);
    if (sum == target) {
      v.push_back(p);
    }
  }
  return v;
}
于 2013-10-07T22:36:09.237 回答
1

这是javascript中的答案:

function subsetsum(A, target) {

//int N = sizeof(A)/sizeof(int), sum = 0;
var N = A.length, sum = 0;

//for(int i = 0; i < N; i++) sum += A[i];
for(var i = 0; i < N; i++) sum += A[i];

// vector<bool> V(sum + 1, 0);
var V = [];

V[0] = [];
for(var i = 0; i < N; i++) {
    for(var j = sum; j >= 0; j--) {
        if(j + A[i] <= sum && V[j]) {
            //Join the subset of the memoized result to this result.
            V[A[i] + j] = [A[i]].concat(V[j]);  
        } 
    }
}
console.log(V);
//evaluates to true if V[target] exists
return !!V[target];
}
于 2013-10-07T22:26:01.593 回答
0

我修改了您的代码以打印数字。

void subsetsum(int A[], int target) {

    int N = sizeof(A) / sizeof(int), sum = 0;

    for (int i = 0; i < N; i++) sum += A[i];

    vector<bool> V(sum + 1, 0);
    V[0] = 1;
    for (int i = 0; i < N; i++)
        for (int j = sum; j >= 0; j--) {
            if (j + A[i] <= sum && V[j]) V[A[i] + j] = 1;
        }
    if (V[target]) cout << "Sumbset sum exists" << endl;
    else cout << "Sumbset sum doesnt exist" << endl;

    if (V[target])
    {
        for (int i = N - 1; i >= 0; i--)
        {
            if (V[target - A[i]] == 1) printf("%d, ", A[i]), target -= A[i];
        }
        printf("\n");
    }
}

或者这是我的带有矢量的版本

bool subsetsum_dp(vector<int>& v, int sum)
{
    int n = v.size();
    const int MAX_ELEMENT = 100;
    const int MAX_ELEMENT_VALUE = 1000;
    static int dp[MAX_ELEMENT*MAX_ELEMENT_VALUE + 1]; memset(dp, 0, sizeof(dp));

    dp[0] = 1;

    for (int i = 0; i < n; i++)
    {
        for (int j = MAX_ELEMENT*MAX_ELEMENT_VALUE; j >= 0; j--)
        {
            if (j - v[i] < 0) continue;
            if (dp[j - v[i]]) dp[j] = 1;
        }
    }
    if (dp[sum])
    {
        for (int i = n - 1; i >= 0; i--)
        {
            if (dp[sum - v[i]] == 1) printf("%d, ", v[i]), sum -= v[i];
        }
        printf("\n");
    }

    return dp[sum] ? true : false;
}
于 2014-12-06T18:52:18.153 回答