将数组划分为2个部分的实现使得这两个部分具有相等的平均值

问题描述 投票:0回答:2

我正在实施this question中描述的相同问题的方法,但我不认为这是有效的。

对于那些不想在那里学习数学的人来说,这里是gist中的代数:

Average = Sum(S1)/n(S1) = Sum(S2)/ n(S2) = Sum(Total)/n(Total) 

where n() stands for the number of elements in the array & Sum() stands for the cumulative sum

S1和S2是阵列Total的互斥子集。因此,为了找到这个条件成立的所需子集,我们找到Sum(S1) = Sum(Total) * n(S1)/n(Total)

我的方法:

#include <bits/stdc++.h>

using namespace std;

bool SubsetSum(vector<int> &A, int Sum)
{
    bool dp[Sum+1][A.size()+1];
    int i, j;
    for(i=0; i<= A.size(); i++)
        dp[0][i] = false; // When sum = 0
    for(i=0; i<=Sum; i++)
        dp[i][0] = 1; // When num of elements = 0
    for(i = 1; i <= A.size(); i++)
    {
        for(j=1; j<= Sum; j++)
        {
            dp[i][j] = dp[i-1][j];
            if(j-A[i-1] >= 0)
                dp[i][j] = dp[i][j] || dp[i-1][j-A[i-1]];
        }
    }
    return dp[Sum][A.size()];
}

void avgset(vector<int> &A) {
    int total = accumulate(A.begin(), A.end(), 0); // Cumulative sum of the vector A
    int ntotal = A.size(); // Total number of elements

    int i;
    for(i=1; i<=ntotal; i++) // Subset size can be anything between 1 to the number of elements in the total subset
    {
        if((total * i) % ntotal == 0)
        {
            if(SubsetSum(A, (total * i)/ntotal)) // Required subset sum = total * i)/ntotal
                cout<<"Array can be broken into 2 arrays each with equal average of "<<(total * i)/ntotal<<endl;
        }
    }
}

int main()
{
    vector<int> A = {1, 7, 15, 29, 11, 9};
    avgset(A);
    return 0;
}

此代码输出:

Array can be broken into 2 arrays each with equal average of 12
Array can be broken into 2 arrays each with equal average of 36
Array can be broken into 2 arrays each with equal average of 60

但这些答案都是错误的。

例如,当子集sum = 12时,相应的元素将是{11, 1}。然后:

(11 + 1)/2 != (7 + 15 + 29 + 9)/4

我在这里误解了什么吗?

algorithm dynamic-programming knapsack-problem subset-sum
2个回答
2
投票

我在这里误解了什么吗?

好像你做到了。

对于给定的阵列,平均值总是等于12 - 总平均值,第一子集平均值,第二子集平均值。

所以你必须检查:

  • 具有和12的1元素子集不存在
  • 具有和24的2元素子集 - 确实存在9 + 15
  • 具有和36的3元素子集 - 不存在

并且无需检查更大的金额(> n / 2)


1
投票

应指定子集和的元素编号。找不到等于n / 2的元素就足够了。还有其他错误。代码如下:

bool SubsetSum(vector<int> &A, int number, int Sum)
{
    bool dp[Sum+1][A.size()+1];
    int i, j;
    for(i=0; i<= A.size(); i++)
        for (j = 0; j <= Sum; j++)
            dp[j][i] = false; // When sum = 0
    dp[0][0] = true; // When num = 0 of 0 elements
    for(i = 1; i <= A.size(); i++)
    {
        for(j=Sum; j>=A[i-1]; j--)
        {
            for (int k = A.size(); k > 0; k--)
                dp[j][k] = dp[j][k] || dp[j-A[i-1]][k-1];
        }
    }
    return dp[Sum][number];
}

void avgset(vector<int> &A) {
    int total = accumulate(A.begin(), A.end(), 0); // Cumulative sum of the vector A
    int ntotal = A.size(); // Total number of elements

    int i;
    for(i=1; i<=ntotal/2; i++) // Subset size can be anything between 1 to the number of elements in the total subset
    {
        if((total * i) % ntotal == 0)
        {
            if(SubsetSum(A, i, (total * i)/ntotal)) // Required subset sum = total * i)/ntotal
                cout<<"Array can be broken into 2 arrays each with equal average of "<<(total * i)/ntotal<<endl;
        }
    }
}

输出:

Array can be broken into 2 arrays each with equal average of 24
© www.soinside.com 2019 - 2024. All rights reserved.