一个均匀和有序的分配问题

时间:2009-08-17 14:43:36

标签: algorithm distribution

我按特定顺序拥有一定数量的方框,并按特定顺序拥有多个权重。重量可以具有不同的重量(即一个可以重1kg,另一个重2kg等)。 我想把重量放在盒子里,以便它们尽可能均匀分布。我必须按照给出的顺序取重量,我必须按照给出的顺序填充方框。也就是说,如果我把重量放在方框n + 1中,我不能将重量放在方框n中,我不能将重量m + 1放在一个方框中,直到我第一次将重量m放在一个方框中。

我需要找到一个算法来解决任何数量的框和任何权重集的问题。

使用xUnit在C#中进行一些测试(Distribute是应该解决问题的方法):

    [Fact]
    public void ReturnsCorrectNumberOfBoxes()
    {
        int[] populatedColumns = Distribute(new int[0], 4);

        Assert.Equal<int>(4, populatedColumns.Length);
    }

    [Fact]
    public void Test1()
    {
        int[] weights = new int[] { 1, 1, 1, 1 };

        int[] boxes = Distribute(weights, 4);

        Assert.Equal<int>(weights[0], boxes[0]);
        Assert.Equal<int>(weights[1], boxes[1]);
        Assert.Equal<int>(weights[2], boxes[2]);
        Assert.Equal<int>(weights[3], boxes[3]);
    }

    [Fact]
    public void Test2()
    {
        int[] weights = new int[] { 1, 1, 17, 1, 1 };

        int[] boxes = Distribute(weights, 4);

        Assert.Equal<int>(2, boxes[0]);
        Assert.Equal<int>(17, boxes[1]);
        Assert.Equal<int>(1, boxes[2]);
        Assert.Equal<int>(1, boxes[3]);
    }

    [Fact]
    public void Test3()
    {
        int[] weights = new int[] { 5, 4, 6, 1, 5 };

        int[] boxes = Distribute(weights, 4);

        Assert.Equal<int>(5, boxes[0]);
        Assert.Equal<int>(4, boxes[1]);
        Assert.Equal<int>(6, boxes[2]);
        Assert.Equal<int>(6, boxes[3]);
    }

非常感谢任何帮助!

2 个答案:

答案 0 :(得分:3)

请参阅下面的解决方案。

干杯,

马拉什

public static int[] Distribute(int[] weights, int boxesNo)
{
    if (weights.Length == 0)
    {
        return new int[boxesNo];
    }

    double average = weights.Average();

    int[] distribution = new int[weights.Length];

    for (int i = 0; i < distribution.Length; i++)
    {
        distribution[i] = 0;
    }

    double avDeviation = double.MaxValue;

    List<int> bestResult = new List<int>(boxesNo);


    while (true)
    {
        List<int> result = new List<int>(boxesNo);

        for (int i = 0; i < boxesNo; i++)
        {
            result.Add(0);
        }

        for (int i = 0; i < weights.Length; i++)
        {
            result[distribution[i]] += weights[i];
        }
        double tmpAvDeviation = 0;

        for (int i = 0; i < boxesNo; i++)
        {
            tmpAvDeviation += Math.Pow(Math.Abs(average - result[i]), 2);
        }
        if (tmpAvDeviation < avDeviation)
        {
            bestResult = result;
            avDeviation = tmpAvDeviation;
        }

        if (distribution[weights.Length - 1] < boxesNo - 1)
        {
            distribution[weights.Length - 1]++;
        }
        else
        {
            int index = weights.Length - 1;
            while (distribution[index] == boxesNo - 1)
            {
                index--;
                if (index == -1)
                {
                    return bestResult.ToArray();
                }
            }
            distribution[index]++;
            for (int i = index; i < weights.Length; i++)
            {
                distribution[i] = distribution[index];
            }
        }
    }
}

答案 1 :(得分:2)

第二次尝试:我认为A *(发音为“a star”)算法在这里运行良好,即使它会占用大量内存。如果有的话,你可以得到最佳答案。

您正在搜索的每个“节点”都是框中权重的可能组合。第一个节点应该是您随机挑选的任何重量,放入一个盒子。我建议随机选择新的重量。

不幸的是,A *很复杂,我没有时间在这里解释。通过自己阅读很容易理解,但如上所述将其映射到这个问题会更加困难。如果您选择此路线,请回复相关问题。