Algorithm 将一个数组分成两部分的实现,使两部分的平均值相等

Algorithm 将一个数组分成两部分的实现,使两部分的平均值相等,algorithm,dynamic-programming,knapsack-problem,subset-sum,Algorithm,Dynamic Programming,Knapsack Problem,Subset Sum,我正在针对同一问题实施中描述的方法,但我认为这不起作用 对于那些不想在那里学习数学的人,这里是代数的要点: 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的互斥子集。因此,为了找到该条件成立

我正在针对同一问题实施中描述的方法,但我认为这不起作用

对于那些不想在那里学习数学的人,这里是代数的要点:

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;
}
但这些答案是错误的

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

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

我误解了吗?

应该指定子集和的元素编号。查找小于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;
        }
    }
}

应指定子集和的元素编号。查找小于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;
        }
    }
}
我是不是误解了什么

看来是你干的

对于给定的数组,平均值始终等于12-总平均值、第一个子集平均值、第二个子集平均值

因此,您必须检查:

  • 总和为12的1元素子集-不存在
  • 和为24的2元素子集-是否存在9+15
  • 总和为36的3元素子集-不存在
无需检查较大的总和(>n/2)

我是不是误解了什么

看来是你干的

对于给定的数组,平均值始终等于12-总平均值、第一个子集平均值、第二个子集平均值

因此,您必须检查:

  • 总和为12的1元素子集-不存在
  • 和为24的2元素子集-是否存在9+15
  • 总和为36的3元素子集-不存在

没有必要检查更大的和(>n/2)

很抱歉,我仍然不明白为什么我们必须检查1元素、2元素和3元素。你能详细说明一下吗?因为这是我们选择的方法-我们正试图用
ave=subsetsum/k
为所有可能的k构建k-子集。真的,我们应该只检查
kI很抱歉,我仍然不明白为什么我们必须检查1元素、2元素和3元素。你能详细说明一下吗?因为这是我们选择的方法-我们正试图用
ave=subsetsum/k
为所有可能的k构建k-子集。实际上,我们应该只检查
kHi,请帮助我理解:(1)。你所说的子集和的元素数是什么意思。(2). 你为什么要削减基本情况。ie:为什么只有
dp[0][0]
是正确的,而不是整个列。我认为整列应该是正确的,因为当我们必须使总和等于0时,总是有一个选项(不要选择任何东西)。(3). 为什么将(j=Sum;j>=A[i-1];j--)的第二个for循环
颠倒过来。(4). (int k=A.size();k>0;k--)的
的目的是什么。Find k*avg应该与k number匹配,因此分区avg是(k*avg)/k=avg.2。只有0元素值为0时为真。应处理其他值。3.不反转也可以,确保[A[i-1],和]中的j。4.k表示和值的元素数,因此可以找到指定数量的元素与和值匹配。您好,请帮助我理解:(1)。你所说的子集和的元素数是什么意思。(2). 你为什么要削减基本情况。ie:为什么只有
dp[0][0]
是正确的,而不是整个列。我认为整列应该是正确的,因为当我们必须使总和等于0时,总是有一个选项(不要选择任何东西)。(3). 为什么将(j=Sum;j>=A[i-1];j--)的第二个for循环
颠倒过来。(4). (int k=A.size();k>0;k--)的
的目的是什么。Find k*avg应该与k number匹配,因此分区avg是(k*avg)/k=avg.2。只有0元素值为0时为真。应处理其他值。3.不反转也可以,确保[A[i-1],和]中的j。4.k表示和值的元素数,因此可以找到与和值匹配的指定数量的元素。
Array can be broken into 2 arrays each with equal average of 24