今天遇到以下问题:
我必须根据大小将物品分类到插槽中,以便插槽最满。如果对此存在多种解决方案,那么我必须考虑已实现的排序优先级分数。 (所以有两种目标函数)。
我想出了一个回溯解决方案,它获取项目(按大小升序)和槽(按大小升序),并通过它们回溯。基本上我们返回的是每个项目,它应该进入的插槽的索引。每个项目都有一个添加的候选者,它是 -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 |
有人可以指出这是错误的方向吗?提前致谢。