因此,我正在努力学习如何为我需要创建的工具打包.所以我使用了来自Bin Packing Problem (Minimize number of used Bins)的以下代码

菲德尔:Wood Pieces Fiddle

    int[] weight = { 345,345,175,175,175,175,470,470,470,470,345,345,175,175,200,200,200,200,300,300,400,400,350 };
    int c = 3000;
    int n = weight.Length;
    Console.Write("Total: " + weight.Sum() + "mm in " + GFG.bestFit(weight, n, c) + " pieces max");

和工作程序:

public static int bestFit(int[] weight, int n, int c)
    {
         
        // Initialize result (Count of bins)
        int res = 0;
 
        // Create an array to store
        // remaining space in bins
        // there can be at most n bins
        int[] bin_rem = new int[n];
 
        // Place items one by one
        for (int i = 0; i < n; i++) {
           
            // Find the best bin that
            // can accommodate
            // weight[i]
            int j;
 
            // Initialize minimum space
            // left and index
            // of best bin
            int min = c + 1, bi = 0;
 
            for (j = 0; j < res; j++) {
                if (bin_rem[j] >= weight[i]
                    && bin_rem[j] - weight[i] < min) {
                    bi = j;
                    min = bin_rem[j] - weight[i];
                }
            }
 
            // If no bin could accommodate weight[i],
            // create a new bin
            if (min == c + 1) {
                bin_rem[res] = c - weight[i];
                res++;
            }
           
            // Assign the item to best bin
            else
                bin_rem[bi] -= weight[i];
        }
        return res;
    }

所以我有两个问题,但主要只有一个:

我试图将程序修改为List<>分,但我错误地失败了.我不需要答案AS-IS,有一个 idea 或方法就可以了,因为我不是在找人为我工作,只是帮助我理解这件事的诀窍在哪里.任何帮助都将被珍视,即使是一条 comments .

可选问题:我不认为是最好的方法(如果我理解得很好的话),因为我没有try 所有的组合和可能性.有没有什么可以改进这个代码的指南?

推荐答案

我建议保留一个数据 struct 来保存所有结果数据,这样就不必保持两个数据 struct 对齐.

此外,我建议使用类似List或类似的数据 struct ,因为它比数组更灵活.你不知道,一个箱子里会有多少个箱子,有多少东西.因此,分配不可调整大小的数组可能不是最好的方法,因为您要么必须使它们足够大以容纳所有元素(并且浪费大量内存),要么总是必须判断它们的大小并在必要时重新分配.

此外,正如 comments 中所解释的那样,我建议将降下来的物品分类,然后再将它们分配到垃圾箱中,因为这样一来,无法放入一个垃圾箱的重物品将首先被分发,然后轻物品可以用来填补剩余的缺口.如果你先分发轻物品,它们会被紧紧地塞进最初的几个垃圾桶里.然后,每个沉重的物品都需要一个垃圾箱,留下大量未使用的容量.

有关该方法的简单实现,请参阅以下代码

//the default capacity of an empty bin
private static in CAPACITY = 3000;

//this is the structure that will represent a single bin, exposing the
//remaining capacity and the items currently contained
class Bin {
    public int capacityLeft {get; set;}
    public List<int> items { get; set;}
}

//alternatively you can also pass an int[] here
//doesn't make any difference
static List<Bin> distributeItems(List<int> items) {
  //create new result list of bins
  var result = new List<Bin>(); 
  //sort the items according to comments above
  //try also just with OrderBy(x => x) to sort ascending and see
  //the effect on the result
  var sortedItems = items.OrderByDescending(x => x);
    
  foreach (var x in sortedItems) {
      if (x > CAPACITY) {
          //skip items that are too heavy, or throw an error if you want
          //throw new Error($"item {x} is too heavy");
          continue; 
      }

      //the smallest remaining capacity so far
      var min = CAPACITY + 1;
      //the index of the bin where to put the current item to
      var index = result.Count;

      //check through all existing bins
      //for the first item, this list will be empty, so the loop's body
      //won't be executed at all
      for (int i = 0; i < result.Count; i++) {
          //does the current bin have enough capacity left
          //and is that remaining capacity minimal?
          if (result[i].capacityLeft >= x && result[i].capacityLeft < min) {
              //define the current bin to be the target for the item
              min = result[i].capacityLeft;
              index = i;
          }
      }
      
      //if no fitting bin was found, index will still be result.Count
      //ie pointing "after" the last element in the result list.
      //this also works for the empty list, as result.Count == index == 0
      //if thats the case, append a new empty bin to the result
      if (index == result.Count) {
          result.Add(new Bin{capacityLeft = CAPACITY, items = new List<int>()});
      }
      
      //put the current item in the respective bin (either the one found
      //in the loop, or the one newly added to the list)
      result[index].capacityLeft -= x;
      result[index].items.Add(x);
  }
    
  return result;
}

另请参阅此fiddle以获取完整的工作示例...

Csharp相关问答推荐

EF Core:看不到任何查询日志(log)?

MongoDB将JS查询转换为C#的问题

Blazor EventCallback<;MyType<;T>;>;

为什么我的表单在绑定到对象时提交空值?

使用带有WithAppOnly()请求选项的pageIterator

自定义列表按字符串的部分排序

用C#从XML内部元素中获取特定值

从Base64转换为不同的字符串返回相同的结果

EF Core:如何对关系属性进行建模?

如何正确处置所有动态控件?

如何使用ODP.NET C#设置Oracle会话时间长度限制

如何在一次数据库调用中为ASP.NET核心身份用户加载角色

Visual Studio如何使用当前的框架?

无效的Zip文件-Zip存档

SignalR跨域

.NET文档对继承的困惑

如何将行添加到DataGrid以立即显示它?

这是T自身的布尔表达式是什么意思?

ASP.NET Core 7空字符串

Roslyn编译器看不到引用