我有一个CardSlot类型的列表,每个CardSlot对象都包含不同的卡,比如Card1,Card2,Card3(数字可能不同)。
每个CardSlot对象都预设了最大数量的Card1,Card2和Card3。现在,用户输入所需的卡数量,并且应该获得满足标准的CardSlot组合。
例如:
List<CardSlot> listCardSlot = new List<CardSlot>();
CardSlot cardSlot1 = new CardSlot();
cardSlot1.Name = "cardSlot1";
cardSlot1.Price = 900;
cardSlot1.Card1 = 2;
cardSlot1.Card2 = 3;
cardSlot1.Card3 = 4;
listCardSlot.Add(cardSlot1);
CardSlot cardSlot2 = new CardSlot();
cardSlot2.Name = "cardSlot2";
cardSlot2.Price = 850;
cardSlot2.Card1 = 3;
cardSlot2.Card2 = 2;
cardSlot2.Card3 = 4;
listCardSlot.Add(cardSlot2);
CardSlot cardSlot3 = new CardSlot();
cardSlot3.Name = "cardSlot3";
cardSlot3.Price = 950;
cardSlot3.Card1 = 4;
cardSlot3.Card2 = 3;
cardSlot3.Card3 = 2;
listCardSlot.Add(cardSlot3);
现在,如果用户输入Card1 = 4,Card2 = 5且Card3 = 4,最终结果应该是CardSlot对象的组合,价格最低。
有人可以给我一个正确方向的推动吗?请告诉我,如果有什么不清楚的地方,我会尝试改进它。
修改
我尝试使用以下功能查找列表中的所有可能组合:
public static List<List<T>> ItemCombinations<T>(List<T> inputList, int minimumItems = 1)
{
int nonEmptyCombinations = (int)Math.Pow(2, inputList.Count) - 1;
List<List<T>> listOfCombinations = new List<List<T>>(nonEmptyCombinations + 1);
if (minimumItems == 0)
listOfCombinations.Add(new List<T>());
for (int i = 1; i <= nonEmptyCombinations; i++)
{
List<T> thisCombination = new List<T>(inputList.Count);
for (int j = 0; j < inputList.Count; j++)
{
if ((i >> j) % 2 != 0)
thisCombination.Add(inputList[j]);
}
if (thisCombination.Count >= minimumItems)
listOfCombinations.Add(thisCombination);
}
return listOfCombinations;
}
这会成功返回所有可能的组合。但是,它仍然没有考虑重复出现同一卡槽可能是正确选择的情况。例如,在上述场景中,正确的选择是1 X CardSlot1 + 1 X CardSlot2
修改2
我达到了一个中间解决方案,并将其作为答案发布,在混合和匹配组合的情况下,它仍然没有给我所需的答案。任何人都可以看看并为此提出建议吗?
答案 0 :(得分:0)
所以我已经为此做了一个解决方案,必须说这对我来说是个头疼,但是我已经尝试过了。
CardSlot 我上课:
public class CardSlot
{
public string Name { get; set; } = "";
public double Price { get; set; } = 0;
public int Card1 { get; set; } = 0;
public int Card2 { get; set; } = 0;
public int Card3 { get; set; } = 0;
}
然后其余部分如下:
//your code
//as above
//in the question
listCardSlot.Add(cardSlot3); //your code
ValueChecker(1);
double lowestamount = mycards.Any() ? mycards.Min(item => item.Price) : 0;
MessageBox.Show("You need " + multiplier.ToString() + " " +
ReturnLowestCardSlot(lowestamount).Name);
}
int a = 4, b = 5, c = 4; //User entered values
int multiplier = 0;
List<CardSlot> mycards = new List<CardSlot>();
CardSlot ReturnLowestCardSlot(double lowestPrice)
{
CardSlot cardslot = null;
foreach (var item in mycards)
{
if (item.Price == lowestPrice)
{
cardslot = item;
break;
}
}
return cardslot;
}
void ValueChecker(int increment)
{
multiplier += increment;
foreach (CardSlot item in listCardSlot)
{
if (((multiplier * item.Card1) >= a) &&
((multiplier * item.Card2) >= b) &&
((multiplier * item.Card3) >= c))
{
if (!(mycards.Contains(item)))
mycards.Add(item);
}
}
if (mycards.Count == 0)
ValueChecker(1);
}
我得到的输出是:
你需要2张cardSlot1
希望你能以某种方式调整这个以满足你的需要
编辑
我看到你希望输出为2 cardslot2
,其中包含:
cardSlot2.Card1 = 3;
cardSlot2.Card2 = 2;
cardSlot2.Card3 = 4;
2 x CardSlot2将给出:
cardSlot2.Card1 = 6;
cardSlot2.Card2 = 4;
cardSlot2.Card3 = 8;
但用户的要求是usercard1 = 4
,usercard1 = 5
&amp; usercard1 = 4
。
此处Card2 = 4
仍然小于usercard2 = 5
我不知道它是如何满足要求的。
编辑2
你的评论是对的,我没有这样做。现在这将给你结果:
//codes same
//as your question
ValueChecker(1);
double lowestamount = mycards.Any() ? mycards.Min(item => item.Price) : 0;
CardSlot leastcard = ReturnLowestCardSlot(lowestamount, mycards);
double lowestamount2 = listCardSlot.Any() ? listCardSlot.Min(item => item.Price) : 0;
CardSlot lowestcard = ReturnLowestCardSlot(lowestamount2, listCardSlot);
if ((leastcard.Price + lowestcard.Price) > (multiplier * leastcard.Price))
MessageBox.Show("You need " + multiplier.ToString() + " " + leastcard.Name);
else
MessageBox.Show("You need 1 " + leastcard.Name + " and 1 " + lowestcard.Name);
}
并修改了ReturnLowestCardSlot
CardSlot ReturnLowestCardSlot(double lowestPrice, List<CardSlot> list)
{
CardSlot cardslot = null;
foreach (var item in list)
{
if (item.Price == lowestPrice)
{
cardslot = item;
break;
}
}
return cardslot;
}
输出:
您需要1张cardSlot1和1张cardSlot2
答案 1 :(得分:0)
感谢Nobody(这听起来很粗鲁:D),这是我达到的中间(尽管不是非常优化)解决方案。这给出了最便宜的组合(CardSlots列表)。
但是,当答案应该是异质解决方案时(例如5 X CardSlot1,3 X CardSlot2,1 X CardSlot3),它不会提供答案。对此有任何帮助将非常感激。
static void Main(string[] args)
{
//Some Code
// Get user input card1, card2, card3
List<List<CardSlot>> validCombination = GetAllCombinations(card1, card2, card3, listCardSlot);
List<CardSlot> CheapestCombo = GetLeastPricedCombination(validCombination);
//Here I get the cheapest homogenous combination
}
private static List<List<CardSlot>> GetAllCombinations(int card1, int card2, int card3, List<CardSlot> listCardSlot)
{
var listOfCombinations = ItemCombinations(listCardSlot, 1);
List<List<CardSlot>> validCombination = new List<List<CardSlot>>();
int multiplier;
foreach (List<CardSlot> combination in listOfCombinations)
{
multiplier = 1;
if (CheckMaterialSum(combination, card1, card2, card3, ref multiplier))
{
validCombination.Add(combination);
}
else
{
GetMultiplierCombination(combination, card1, card2, card3, ref validCombination, ref multiplier);
}
}
return validCombination;
}
private static bool CheckMaterialSum(List<CardSlot> combination, int card1, int card2, int card3, ref int multiplier)
{
int sumcard1 = multiplier * (combination.Sum(comb => comb.Card1));
int sumcard2 = multiplier * (combination.Sum(comb => comb.Card2));
int sumcard3 = multiplier * (combination.Sum(comb => comb.Card3));
if (sumcard1 >= card1 && sumcard2 >= card2 && sumcard3 >= card3)
{
return true;
}
return false;
}
private static void GetMultiplierCombination(List<CardSlot> combination, int card1, int card2, int card3, ref List<List<CardSlot>> validCombination, ref int multiplier)
{
while (!CheckMaterialSum(combination, card1, card2, card3, ref multiplier))
{
multiplier += 1;
}
List<CardSlot> interMediateCombo = new List<CardSlot>();
for (int i = 0; i < multiplier; i++)
{
interMediateCombo.AddRange(combination);
}
validCombination.Add(interMediateCombo);
}
private static List<CardSlot> GetLeastPricedCombination(List<List<CardSlot>> validCombination)
{
List<CardSlot> cheapestCombo = new List<CardSlot>();
int leastPrice = int.MaxValue;
int priceTotal;
//Find better way for finding least priced combination
foreach (List<CardSlot> combination in validCombination)
{
priceTotal = combination.Sum(combo => combo.Price);
if (priceTotal < leastPrice)
{
leastPrice = priceTotal;
}
}
foreach (List<CardSlot> combination in validCombination)
{
priceTotal = combination.Sum(combo => combo.Price);
if(priceTotal == leastPrice)
{
cheapestCombo.AddRange(combination);
break;
}
}
return cheapestCombo;
}