C#复杂目标函数优化问题

问题描述 投票:0回答:0

今天遇到以下问题:

我必须根据大小将物品分类到插槽中,以便插槽最满。如果对此存在多种解决方案,那么我必须考虑已实现的排序优先级分数。 (所以有两种目标函数)。

我想出了一个回溯解决方案,它获取项目(按大小升序)和槽(按大小升序),并通过它们回溯。基本上我们返回的是每个项目,它应该进入的插槽的索引。每个项目都有一个添加的候选者,它是 -1,作为一个不可能的索引,这意味着该项目没有被放入任何插槽。

它找到了一个完美的解决方案,以最佳方式填充插槽,但遗憾的是优先点系统不知何故被破坏了。

internal class Slot
{
    int Size;
}

internal class Item
{
    int Size;
    PriorityEnum Priority;
    //1 - Critical
    //2 - High
    //3 - Medium
    //4 - Low
}

internal class SlotFillBackTrack {
    private int LvlNum;
    private int[] Candidates;
    private Item[] UpForSortItems;
    private Slot[] slots;
    internal SlotFillBackTrack(Item[] items, Slot[] slots) {
        LvlNum = items.Length;
        Candidates = new int[slots.Length + 1];
        this.slots = slots;
        UpForSortItems = items;
        for (int i = 0; i < Candidates.Length; i++) {
            Candidates[i] = i - 1;
        }
    }
    internal int[] StartSearch() {
        if (LvlNum > 0) {
            bool found = false;
            List < int > Current = new List < int > ();
            int[] Opt = new int[LvlNum];
            BacktrackOpt(ref Current, ref found, ref Opt);
            if (found) {
                return Opt;
            }
            throw new Exception("No solution");
        }
        throw new Exception("Nothing to sort!");
    }
    private void BacktrackOpt(ref List < int > Current, ref bool found, ref int[] Opt) {
        if (Current.Count == LvlNum) {
            if (!found) {
                Current.CopyTo(Opt, 0);
                found = true;
            } else if (LoadingScore(Current.ToArray()) > LoadingScore(Opt)) {
                Current.CopyTo(Opt, 0);
            } else if (LoadingScore(Current.ToArray()) == LoadingScore(Opt) &&
                PriorityScore(Current.ToArray()) > PriorityScore(Opt)) {
                Current.CopyTo(Opt, 0);
            }
            return;
        }
        for (int i = 0; i < Candidates.Length; i++) {
            if (IsValidMove(Current.Count, Candidates[i], Current)) {
                Current.Add(Candidates[i]);
                BacktrackOpt(ref Current, ref found, ref Opt);
                Current.Remove(Candidates[i]);
            }
        }
    }
    private bool IsValidMove(int level, int candidate, List < int > alreadyChosen) {
        if (r < 0) {
            return true;
        }
        int emptySpaceInSlot = slots[candidate].Size;
        for (int i = 0; i < alreadyChosen.Count; i++) {
            if (alreadyChosen[i] == candidate) {
                emptySpaceInSlot -= UpForSortItems[i].Size;
            }
        }
        return emptySpaceInSlot >= UpForSortItems[level].Size;
    }
    private int LoadingScore(int[] E) {
        int usedSpace = 0;
        int allSpace = 0;
        for (int i = 0; i < slots.Length; i++) {
            allSpace += slots[i].Size;
        }
        for (int i = 0; i < E.Length; i++) {
            if (E[i] != -1) {
                usedSpace += UpForSortItems[i].Size;
            }
        }
        return usedSpace - allSpace;
    }
    private int PriorityScore(int[] E) {
        int sum = 0;
        for (int i = 0; i < E.Length; i++) {
            if (E[i] != -1) {
                sum += 5 - (int) UpForSortItems.Priority;
            }
        }
        return sum;
    }
}

对于以下输入:

插槽:

插槽1:大小 = 20
插槽2:大小 = 30
插槽3:大小= 60

项目

项目1 大小 = 15;优先级 = 2(高)
项目2 大小 = 20;优先级 = 1(严重)
项目3 大小 = 30;优先级 = 1(严重)
项目4 大小 = 45;优先级 = 2(高)
项目5 大小 = 60;优先级 = 1(严重)

插槽(尺寸) 预期项目(大小,优先级) 收到的物品(尺寸、优先级)
插槽1 (20) 项目2 (20, 1) 项目2 (20, 1)
插槽2 (30) 项目3 (30, 1) 项目3 (30, 1)
插槽2 (60) 项目4 (45, 2), 项目1 (15, 2) 项目5 (60, 1)
优先点(见代码) 5-1+5-1+5-2+5-2 = 14 5-1+5-1+5-1 = 12

有人可以指出这是错误的方向吗?提前致谢。

c# optimization backtracking recursive-backtracking
© www.soinside.com 2019 - 2024. All rights reserved.