C# 一个类似于背包问题的规划问题
我曾在一些stackexchange网站上询问过这一问题,他们告诉我,我应该在这里询问,并提供代码,因此: 整个问题类似于背包问题,但得到了扩展 有一个背包,上面有:C# 一个类似于背包问题的规划问题,c#,knapsack-problem,C#,Knapsack Problem,我曾在一些stackexchange网站上询问过这一问题,他们告诉我,我应该在这里询问,并提供代码,因此: 整个问题类似于背包问题,但得到了扩展 有一个背包,上面有: 重量 耐久性 最大进度 最高质量 有一些项目。每个项目都有: 重量, 耐久性损失或增益, 有助于进步的价值观, 有助于提高质量的价值 还有一些添加“buff”的项目: 增加有助于背包进步和/或质量的价值 对于接下来的n项 减少接下来n个项目的耐久性损失 挑选下n件物品后增加耐用性 n取决于buff 背包从重量、耐久性、0进
- 重量
- 耐久性
- 最大进度
- 最高质量
- 增加有助于背包进步和/或质量的价值 对于接下来的n项
- 减少接下来n个项目的耐久性损失
- 挑选下n件物品后增加耐用性
- n取决于buff
- 背包增加重量
- 背包获得进步
- 背包获得质量
- 背包失去或获得耐久性
int maxWeight = 10;
int durability = 60;
int maxProgress = 100;
int maxQuality = 100;
int[] itemWeights = new[] { 1, 1, 2, 3, 1, 1 };
int[] itemDurability = new[] { 10, 0, 20, -15, 10, 10 };
int[] itemProgress = new[] { 20, 0, 40, 0, 0, 0 };
int[] itemQuality = new[] { 0, 0, 25, 0, 0, 0 };
int[] buffs = new[] { 0, 1, 0, 0, 2, 3 };
//buff 1: for 4 next items after picking increase knapsack durability by 5
//buff 2: for 2 next items after picking increase progress gain by 50%
//buff 2: for 2 next items after picking increase quality gain by 50%
这只是一个简单的示例代码。实际项目包括20多个动作,进度和质量取决于其他变量,整个项目相当大,可能会使事情变得复杂。但是,如果您需要完整的源代码,可以提供
我所尝试的:
使用遗传算法来找到最优化的解决方案,这是可行的,但我想要一个数学解决方案。
使用动态规划,首先解决质量问题,然后继续进行。添加“buff”的物品会让事情变得复杂,因为它们没有实际价值
来自实际项目的暴力尝试:
private void SolveForCurrentItems(Items[] availableItems, Items[] items)
{
Knapsack.RemoveItems();
Knapsack.AddItems(items);
var currentItems = Knapsack.GetItems();
//Knapsack.GetItems() returns items that are used
//if picking is no longer possible, last item is not included
if (currentItems.Length == items.Length)
{
for (int i = 0; i < availableItems.Length; i++)
{
var newItems = new Item[currentItems.Length + 1];
currentItems .CopyTo(newItems , 0);
newItems [newItems .Length - 1] = availableItems[i];
SolveForCurrentItems(availableItems, newItems);
}
}
}
增益等级:
public enum BuffType
{
DurabilityRestoration,
DurabilityModifier,
Progress,
Quality
}
public class Buff
{
public int CurrentStack;
public bool NeedsRemove { get; set; }
public BuffType BuffType { get; private set; }
public Buff(BuffType buffType)
{
BuffType = buffType;
}
public void Step(Knapsack knapsack)
{
CurrentStack--;
if (CurrentStack == 0)
NeedsRemove = true;
}
}
如何使用它的示例:
Knapsack knapsack = new Knapsack { MaxWeight = 100, Durability = 60, MaxProgress = 100, MaxQuality = 100 };
Item[] items = new Item[]
{
new Item {Weight = 1, Durability = 10, Progress = 20, Quality = 0, HasBuff = false },
new Item {Weight = 1, Durability = 0, Progress = 0, Quality = 0, HasBuff = true, Buff = new Buff(BuffType.DurabilityRestoration) },
new Item {Weight = 4, Durability = 15, Progress = 5, Quality = 25, HasBuff = false },
new Item {Weight = 3, Durability = -15, Progress = 0, Quality = 0, HasBuff = false },
new Item {Weight = 1, Durability = 10, Progress = 0, Quality = 0, HasBuff = true, Buff = new Buff(BuffType.Progress) },
new Item {Weight = 1, Durability = 10, Progress = 0, Quality = 0, HasBuff = true, Buff = new Buff(BuffType.Quality) },
};
knapsack.CurrentItems.Add(items[4]);
knapsack.CurrentItems.Add(items[1]);
knapsack.CurrentItems.Add(items[5]);
knapsack.CurrentItems.Add(items[2]);
knapsack.CurrentItems.Add(items[2]);
knapsack.CurrentItems.Add(items[3]);
knapsack.CurrentItems.Add(items[2]);
knapsack.CurrentItems.Add(items[2]);
knapsack.CurrentItems.Add(items[1]);
knapsack.CurrentItems.Add(items[3]);
knapsack.CurrentItems.Add(items[3]);
knapsack.CurrentItems.Add(items[4]);
knapsack.CurrentItems.Add(items[0]);
knapsack.CurrentItems.Add(items[0]);
knapsack.CurrentItems.Add(items[4]);
knapsack.CurrentItems.Add(items[0]);
knapsack.ExecuteItems();
我想要的是一个以最佳方式解决问题的算法。您已将问题标记为C,因此我建议您使用它的强大功能。 因此,与其使用单独的项目属性列表,不如使用具有这些属性的项目类,例如
interface IItem
{
int Weight{get;set;}
int Durability {get;set;}
int Progress {get;set;}
int Quality {get;set;}
int Buff {get;set;}
}
class Item1 : IItem
{
...
}
class Item2 : IItem
{
...
}
…
然后你的背包
类可以有一个IItem
类的集合,它是内容
然后,如果您有一个所有基于IItem
的唯一类的完整列表,您可以根据您感兴趣的属性对它们进行排序,并根据其标准(例如重量可能太高)选择可以放入背包中的类,因此您可以选择重量较低的IItem
已编辑
好吧,你最近的帖子让我原来的帖子过时了,所以有人投了反对票
尽管如此,我认为您想要的是根据您已有的标准在代码中执行某种Venn图逻辑
让我解释一下
您的目标是以最少的项目数量达到最高质量和进度,因此请按质量(最高优先)对所有项目进行排序,并不断将此排序列表中的实例添加到质量列表中,直到您达到尽可能接近最大的质量。如果当前实例不适合,请转到列表中的下一个实例并检查是否适合
对每个项目属性执行相同的过程
然后,您可以确定列表的相交位置,结果输出将接近您的最佳项目选择
我有一个明显的印象,您可能希望每个项目类型都是唯一的类,并且它们都实现相同的接口,或者它们都有一个指示其类型的属性,如果你能确定最后选择了哪一个就好了。你已经将问题标记为C,因此我建议你使用它的威力。
因此,与其使用单独的项目属性列表,不如使用具有这些属性的项目类,例如
interface IItem
{
int Weight{get;set;}
int Durability {get;set;}
int Progress {get;set;}
int Quality {get;set;}
int Buff {get;set;}
}
class Item1 : IItem
{
...
}
class Item2 : IItem
{
...
}
…
然后你的背包
类可以有一个IItem
类的集合,它是内容
然后,如果您有一个所有基于IItem
的唯一类的完整列表,您可以根据您感兴趣的属性对它们进行排序,并根据其标准(例如重量可能太高)选择可以放入背包中的类,因此您可以选择重量较低的IItem
已编辑
好吧,你最近的帖子让我原来的帖子过时了,所以有人投了反对票
尽管如此,我认为您想要的是根据您已有的标准在代码中执行某种Venn图逻辑
让我解释一下
您的目标是以最少的项目数量达到最高质量和进度,因此请按质量(最高优先)对所有项目进行排序,并不断将此排序列表中的实例添加到质量列表中,直到您达到尽可能接近最大的质量。如果当前实例不适合,请转到列表中的下一个实例并检查是否适合
对每个项目属性执行相同的过程
然后,您可以确定列表的相交位置,结果输出将接近您的最佳项目选择
我有一个明显的印象,您可能希望您的每个项目类型都是一个唯一的类,并且它们都实现相同的接口,或者它们都有一个指示其类型的属性,如果只是为了让您能够确定您在最后选择了哪些。请提供
interface IItem
{
int Weight{get;set;}
int Durability {get;set;}
int Progress {get;set;}
int Quality {get;set;}
int Buff {get;set;}
}
class Item1 : IItem
{
...
}
class Item2 : IItem
{
...
}
…