【问题标题】:Evenly distribute collection into new Arrays将集合均匀分布到新数组中
【发布时间】:2012-07-13 10:54:40
【问题描述】:

我正在尝试创建一种方法来将数组平均分配到 X 个新数组中,其中仅允许 15 个项目 pr 数组,并且您只能创建一个新数组,如果前一个有 10 个项目, 除非数组少于 10 项。

编辑

为了让未来的读者更容易理解我的问题。

  • 这就像一块布。
  • 您需要构建 X 个产品。
  • 为员工打造一款产品需要 T 量。

你需要多少员工,你如何分担他们之间的工作量?

结束编辑

 Max allowed number in array = 15;
 Min allowed number in array = 10;    

 Number = Numbers of Items in the Collection.

 Number  5 =>   [5]
 Number 13 =>   [13]
 Number 16 =>   [10] [6]
 Number 29 =>   [15] [14]
 Number 30 =>   [15] [15]
 Number 31 =>   [11] [10] [10]
 Number 32 =>   [12] [10] [10]
 Number 33 =>   [11] [11] [11]

我正在尝试用 C# 解决这个问题。

到目前为止,这是我的代码,但在 16 = [16]、29 = [19][10]、38 = [18][10][10] 等数字处失败

const int maxAllowedOrderLines = 15;
const int minAllowedOrderLines = 10;
var optimalOrderDisp = new List<int>();

Console.WriteLine("Number of OrderLines");
int linjer = Convert.ToInt32(Console.ReadLine());

if (linjer <= maxAllowedOrderLines)
   optimalOrderDisp.Add(linjer);
else
{
   for (var i = maxAllowedOrderLines; i > 0; i--)
   {
      var maxOrderLines = linjer%i;
      if (maxOrderLines == 0 || i <= minAllowedOrderLines || linjer < maxAllowedOrderLines)
      {
         Console.WriteLine("Optimal number of order lines {0}--{1}", i, (double) linjer/(double) i);

          var optimalNumberOfOrders = linjer/i;
          for (var orderNumber = 0; orderNumber < optimalNumberOfOrders; orderNumber++)
          {
             optimalOrderDisp.Add(i);
          }

          if (maxOrderLines != 0)
             optimalOrderDisp[0] += maxOrderLines;
          break;
       }
    }
 }
 foreach (var i1 in optimalOrderDisp)
 {
    Console.Write("[{0}]", i1);
 }
 Console.WriteLine();

【问题讨论】:

  • 你想让我们做什么?怎么会失败?看起来像家庭作业:)
  • 为什么不是 31 - Number 31 =&gt; [15][10][6]
  • #Adam Houldsworth Nope :-) 我上学已经好几年了。
  • 啊 - 因为它总是会尝试符合最小/最大约束...
  • #El Ronnoco 我添加了失败的输出,希望对您有所帮助。关于 31 号,您的建议分布不均。前任。 Max = 30,您的排序将是 [30][1]

标签: c# .net algorithm language-agnostic


【解决方案1】:

嗯……

const double bucketSize = 15.0;
var totalItems = (double)linjer;
var optimumBuckets = Math.Ceiling(totalItems / bucketSize);
var itemsPerBucket = (int)Math.Ceiling(totalItems / optimumBuckets);

var buckets = new int[(int)optimumBuckets];

var itemsLeft = (int)totalItems
for (var i = 0; i < buckets.length; i++)
{
    if (itemsLeft < itemsPerBucket)
    {
        buckets[i] = itemsLeft;
    }
    else
    {
        buckets[i] = itemsPerBucket;
    }
    itemsLeft -= itemsPerBucket;
}

似乎做你想做的事。

【讨论】:

  • 请注意,他的存储桶大小也有一个下限 - 在他的情况下为 10。您的解决方案没有考虑到这一点。
  • @SimonEjsing 没必要,除非你想在条件不满足的情况下抛出异常。
  • 问题是:数字 16 => [10] [6] 你的解决方案不会产生 [8] [8] 吗?
  • @Jodrell 正在测试它,我看起来我能找到的最低项目数是 8。所以我想我会使用你的解决方案,因为它是最简单的。尽管 Simon Ejsing 解决方案产生了正确的结果。
  • @SimonEjsing 你是对的。我认为[8] [8] 是一个更好的答案,但不是确切的问题。我已经投了相应的票。
【解决方案2】:

有趣的问题。我已经尝试过了:

    const int maxAllowedOrderLines = 15;
    const int minAllowedOrderLines = 10;

    static List<int> optimalOrderDisp = new List<int>();

    static void Main(string[] args)
    {
        int Lines = Convert.ToInt32(Console.ReadLine());

        int MinNumberOfBuckets = (int) Math.Ceiling((double) Lines / minAllowedOrderLines);
        int RemainingLines = Lines;
        int BucketLines = Lines / MinNumberOfBuckets;

        // Distribute evenly
        for (int i = 0; i < MinNumberOfBuckets; i++)
        {
            optimalOrderDisp.Add(i != MinNumberOfBuckets - 1 ? BucketLines : RemainingLines);
            RemainingLines -= BucketLines;
        }

        // Try to remove first bucket
        while (RemoveBucket())
        {
        }

        // Re-balance
        Lines = optimalOrderDisp.Sum();
        RemainingLines = Lines;
        BucketLines = (int) Math.Round((double) Lines / (optimalOrderDisp.Count));
        for (int i = 0; i < optimalOrderDisp.Count; i++)
        {
            optimalOrderDisp[i] = (i != optimalOrderDisp.Count - 1 ? BucketLines : RemainingLines);
            RemainingLines -= BucketLines;
        }

        // Re-balance to comply to min size
        for (int i = 0; i < optimalOrderDisp.Count - 1; i++)
            if (optimalOrderDisp[i] < minAllowedOrderLines)
            {
                int delta = minAllowedOrderLines - optimalOrderDisp[i];

                optimalOrderDisp[i] += delta;
                optimalOrderDisp[optimalOrderDisp.Count - 1] -= delta;
            }

        Console.WriteLine(String.Join("\n", optimalOrderDisp.ToArray()));
    }

    static bool RemoveBucket()
    {
        if (optimalOrderDisp.Sum() > maxAllowedOrderLines * (optimalOrderDisp.Count - 1))
            return false;

        int Lines = optimalOrderDisp[0];
        int RemainingLines = Lines;
        int BucketLines = Lines / (optimalOrderDisp.Count - 1);

        // Remove bucket and re-distribute content evenly
        // Distribute evenly
        for (int i = 1; i < optimalOrderDisp.Count; i++)
        {
            optimalOrderDisp[i] += (i != optimalOrderDisp.Count - 1 ? BucketLines : RemainingLines);
            RemainingLines -= BucketLines;
        }

        optimalOrderDisp.RemoveAt(0);
        return true;
    }

【讨论】:

  • 注意,我通过悲观地分配然后反复删除桶(如果合适的话)来稍微翻转它。这可能不是最佳解决方案,但我尝试了您报告的棘手数字并且它有效。我的解决方案将备用值放在最后一个桶中。如果你需要它在第一个,你可以翻转数组。
猜你喜欢
  • 1970-01-01
  • 2020-01-15
  • 2011-04-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多