You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C# 6米钢筋切割长度优化程序问题排查求助

问题排查与修复方案

原代码的核心问题

  1. 索引错误导致元素被跳过:在for循环中执行RemoveAt(i)后,列表长度缩短,但i仍会递增,导致下一个元素被跳过,无法检查是否能加入当前组。比如原列表降序后是3200,3100,2900,2700,...,第一次处理完3200(i=0)后,移除元素,i变为1,直接跳过了3100的检查。
  2. 局部贪心的局限性:原算法每次优先加最大元素,会错过全局更优的组合(比如3100+2900=6000余料为0的组合)。
  3. 组构建不彻底:仅遍历一次列表就结束组构建,导致可加入当前组的小元素被遗漏(比如最后一组的800本可和1200、670合并)。

修复后的基础版本(解决索引问题)

先解决元素被跳过的问题,确保每个元素都能被正确检查:

const int BAR_LENGTH = 6000;

List<int> cuts = new() { 3200, 800, 3100, 2900, 1200, 690, 2700, 1200, 1100, 980, 670 };
List<string> cutsOptimized = new();
cuts.Sort();
cuts.Reverse();

int cutSum = 0;
string cutGroup = "";

while (cuts.Count > 0)
{
    for (int i = 0; i < cuts.Count; i++)
    {
        if (cutSum + cuts[i] <= BAR_LENGTH)
        {
            cutSum += cuts[i];
            cutGroup += cuts[i].ToString() + ",";
            cuts.RemoveAt(i);
            i--; // 修复索引,避免跳过元素
        }
    }

    // 移除末尾多余的逗号
    if (!string.IsNullOrEmpty(cutGroup))
    {
        cutGroup = cutGroup.TrimEnd(',');
    }
    cutsOptimized.Add(cutGroup);
    cutGroup = "";
    cutSum = 0;
}

Console.WriteLine(string.Join(Environment.NewLine, cutsOptimized));

优化版本(优先匹配无余料组合)

为了得到更优的结果,先优先处理刚好凑成6000的组合(余料为0),再用修复后的贪心算法处理剩余元素:

const int BAR_LENGTH = 6000;

List<int> cuts = new() { 3200, 800, 3100, 2900, 1200, 690, 2700, 1200, 1100, 980, 670 };
List<string> cutsOptimized = new();

// 先处理两两凑整的最优组合
for (int i = cuts.Count - 1; i >= 0; i--)
{
    int target = BAR_LENGTH - cuts[i];
    int matchIndex = cuts.IndexOf(target);
    if (matchIndex != -1 && matchIndex != i)
    {
        cutsOptimized.Add($"{cuts[i]},{cuts[matchIndex]}");
        // 先移除索引大的元素,避免索引错乱
        cuts.RemoveAt(Math.Max(i, matchIndex));
        cuts.RemoveAt(Math.Min(i, matchIndex));
        i--; // 移除元素后调整索引
    }
}

// 剩余元素降序排序,用修复后的贪心算法处理
cuts.Sort();
cuts.Reverse();

int cutSum = 0;
string cutGroup = "";

while (cuts.Count > 0)
{
    bool added = false;
    for (int i = 0; i < cuts.Count; i++)
    {
        if (cutSum + cuts[i] <= BAR_LENGTH)
        {
            cutSum += cuts[i];
            cutGroup += cuts[i].ToString() + ",";
            cuts.RemoveAt(i);
            i--;
            added = true;
        }
    }
    // 处理无法再添加元素的剩余单个元素
    if (!added)
    {
        cutGroup += cuts[0].ToString();
        cuts.RemoveAt(0);
    }
    cutGroup = cutGroup.TrimEnd(',');
    cutsOptimized.Add(cutGroup);
    cutGroup = "";
    cutSum = 0;
}

Console.WriteLine(string.Join(Environment.NewLine, cutsOptimized));

这个版本会优先输出3100,2900(余料0),再输出3200,2700(余料100),后续组合的余料也会更小,符合预期。


关键说明

  • 索引修复是基础:移除元素后i--,确保每个元素都能被检查到。
  • 优先凑整是简单有效的优化:在贪心算法基础上,先锁定无余料的最优组合,大幅减少总余料。
  • 代码保持简洁:没有使用复杂算法(如动态规划),适合入门开发者理解和修改。

内容的提问来源于stack exchange,提问作者PhiCato

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 20:43:14