我正在努力学习我需要编写的算法。我正在使用C#。
说我有一个List<Bag>
我有一个List<Lunch>
。
我需要编写一个算法,列出所有行李中所有午餐的排列。
例如,假设有3个午餐和2个袋子:
// Permutation 1
Bag 1, Lunch 1
Bag 2, Lunch 1
// Permutation 2
Bag 1, Lunch 1
Bag 2, Lunch 2
// Permutation 3
Bag 1, Lunch 1
Bag 2, Lunch 3
// Permutation 4
Bag 1, Lunch 2
Bag 2, Lunch 1
// Permutation 5
Bag 1, Lunch 2
Bag 2, Lunch 2
// Permutation 6
Bag 1, Lunch 2
Bag 2, Lunch 3
// Permutation 7
Bag 1, Lunch 3
Bag 2, Lunch 1
// Permutation 8
Bag 1, Lunch 3
Bag 2, Lunch 2
// Permutation 9
Bag 1, Lunch 3
Bag 2, Lunch 3
两个排列Bag 1 Lunch 1 and Bag 2 Lunch 2
和Bag 1 Lunch 2 and Bag 2 Lunch 1
是不同的,因为行李具有不同的容量,因此它们都需要被枚举。
行李和午餐的数量可以是任意数量。
我创建了一个名为BagLunch
的类,其中包含一个包和午餐对。我上面给出的示例列表将存储在List<BagLunch>
。
谢谢。
答案 0 :(得分:4)
在LINQ中使用交叉连接:
var qry = from bag in bags
from lunch in lunches
select new BagLunch
{ Bag=bag, Lunch=lunch};
var baglunches = qry.ToList();
修改强>
您需要修改select子句以处理BagLunch
类的结构。
答案 1 :(得分:2)
如果您允许欺骗[午餐可以分为两袋] - 例如建议您有#bags^#lunches
种可能性。
每个包都有自己独特的“选择”午餐
为了创造这些可能性 - 只需“选择”一个袋子的午餐,并递归地调用算法。每个午餐重复一次。
用于生成它们的伪代码:
generateAll(bags,lunches,sol):
if (bags is empty):
print sol
return
bag <- bags.first
bags.remove(bag)
for each lunch in lunches:
sol.append(BagLunch(bag,lunch)
generateAll(bags,lunches,sol)
sol.removeLast()
答案 2 :(得分:0)
所以你想在保持秩序的同时超过n(k =行李,n =午餐)的k?我希望你可以假设k <= n,否则你会被空袋子困住......
我不想完全破坏你的作业,所以我只是指出你正确的方向。这需要递归。首先选择第一个袋子的午餐,然后选择剩下的k-1袋的午餐。如果您只剩下一个行李,请选择每个剩余的午餐,直到您完成。
编辑:
哦,午餐可以一次放在两个袋子里。所以它是n ^ k。最短的方法是使用上面建议的LINQ交叉连接,但感觉有点像作弊。相反,只需创建一个K元素的整数数组,用零填充它,然后开始向最右边的元素添加一个元素。当它到达N时,将其重置为零并将一个元素带到下一个元素。您只计算base-N中的K位数字。每次迭代后,您都可以输出行李分配。
答案 3 :(得分:0)
我有一个方法可以重新创建上面的示例。这种方法实际上是把袋子想象成一个数字的位置......因为如果你看一下你的例子,你可以把它读成11,12,13,21,22,23。然后是转换到基础Lunch.Count的问题。我也从这里偷了一个方法:https://stackoverflow.com/a/95331/483179转换为它提到的未经测试的任何基础,因此你可能需要构建更健壮的东西。最后,我没有进行任何边缘条件测试,所以喂0袋可能会产生意想不到的结果。这就是我想出的。
class Program
{
static List<Bag> bags = new List<Bag>();
static List<Lunch> lunches = new List<Lunch>();
static void Main(string[] args)
{
lunches.Add(new Lunch() { Num = 1 });
lunches.Add(new Lunch() { Num = 2 });
lunches.Add(new Lunch() { Num = 3 });
bags.Add(new Bag() { Num = 1 });
bags.Add(new Bag() { Num = 2 });
int count = 0;
while (count < Math.Pow(lunches.Count, bags.Count))
{
Console.WriteLine("Permutation " + count);
string countNumber = ConvertToBase(count, lunches.Count).PadLeft(bags.Count,'0');
for (int x = 0; x < bags.Count; x++)
{
Console.WriteLine(bags[x] + " " + lunches[Convert.ToInt32((""+countNumber[x]))]);
}
Console.WriteLine("");
count++;
}
Console.ReadLine();
}
static string ConvertToBase(int value, int toBase)
{
if (toBase < 2 || toBase > 36) throw new ArgumentException("toBase");
if (value < 0) throw new ArgumentException("value");
if (value == 0) return "0"; //0 would skip while loop
string AlphaCodes = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
string retVal = "";
while (value > 0)
{
retVal = AlphaCodes[value % toBase] + retVal;
value /= toBase;
}
return retVal;
}
}
class Lunch
{
public int Num { get;set;}
public override string ToString()
{
return "Lunch " + Num;
}
}
class Bag
{
public int Num { get;set;}
public override string ToString()
{
return "Bag " + Num;
}
}
和结果输出:
Permutation 0
Bag 1 Lunch 1
Bag 2 Lunch 1
Permutation 1
Bag 1 Lunch 1
Bag 2 Lunch 2
Permutation 2
Bag 1 Lunch 1
Bag 2 Lunch 3
Permutation 3
Bag 1 Lunch 2
Bag 2 Lunch 1
Permutation 4
Bag 1 Lunch 2
Bag 2 Lunch 2
Permutation 5
Bag 1 Lunch 2
Bag 2 Lunch 3
Permutation 6
Bag 1 Lunch 3
Bag 2 Lunch 1
Permutation 7
Bag 1 Lunch 3
Bag 2 Lunch 2
Permutation 8
Bag 1 Lunch 3
Bag 2 Lunch 3