【问题标题】:Implementation of partition an array into 2 parts such that the two parts have equal average将数组分成两部分的实现,使得两部分具有相等的平均值
【发布时间】:2019-02-12 22:56:54
【问题描述】:

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

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

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

S1S2 是数组 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

但这些答案是错误的。

例如,当子集总和 = 12 时,对应的元素将为{11, 1}。然后:

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

我在这里误解了什么吗?

【问题讨论】:

    标签: algorithm dynamic-programming knapsack-problem subset-sum


    【解决方案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
    

    【讨论】:

    • 嗨,请帮我理解:(1)。 element number of subset sum 是什么意思。 (2)。你为什么要修剪基本情况。即:为什么只有dp[0][0] 是真的,而不是整个专栏。我认为整个专栏应该是正确的,因为当我们必须使 Sum = 0 时,总是有 1 个选项(不要选择任何东西)。 (3)。为什么要反转第二个 for 循环 for(j=Sum; j&gt;=A[i-1]; j--)。 (4)。 for (int k = A.size(); k &gt; 0; k--)的目的是什么
    • 1.查找 k * avg 应该匹配 k 个数,因此分区 avg 为 (k*avg)/k = avg。 2.只有0元素值为0为真。应该处理其他值。 3. 不反向也可以,确保[A[i-1], Sum]中的j。 4. k 表示求和值的元素个数,因此可以找到与求和值匹配的指定数量元素。
    【解决方案2】:

    我在这里误解了什么吗?

    看来你做到了。

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

    所以你必须检查:

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

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

    【讨论】:

    • 对不起,我仍然不明白为什么我们必须检查 1 元素、2 元素和 3 元素。能详细点吗?
    • 因为这是选择的方法 - 我们正在尝试使用ave = subsetsum / k 为所有可能的 k 构建 k 子集。真的,我们应该只检查k&lt;= n/2
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-07-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多