C# 农民需要通过自参考动物表循环的算法
问题:农场里有很多动物。每种动物都可以有任意数量的动物朋友,反社会动物除外——它们没有属于自己的朋友,但它们作为朋友属于其他正常动物。每一种动物都和它最不快乐的动物朋友一样快乐,当然除了反社会的动物。反社会动物的快乐水平可以是任何东西 一天早上,所有的动物醒来,发现一些反社会动物的情绪发生了变化。农夫是如何计算出每只动物的幸福感的 这里是农场工人们所能看到的(他们没有上过农民学校):C# 农民需要通过自参考动物表循环的算法,c#,algorithm,design-patterns,database-design,C#,Algorithm,Design Patterns,Database Design,问题:农场里有很多动物。每种动物都可以有任意数量的动物朋友,反社会动物除外——它们没有属于自己的朋友,但它们作为朋友属于其他正常动物。每一种动物都和它最不快乐的动物朋友一样快乐,当然除了反社会的动物。反社会动物的快乐水平可以是任何东西 一天早上,所有的动物醒来,发现一些反社会动物的情绪发生了变化。农夫是如何计算出每只动物的幸福感的 这里是农场工人们所能看到的(他们没有上过农民学校): DataTable animals=选择所有动物(); foreach(动物中的动物数据行。行) { int
DataTable animals=选择所有动物();
foreach(动物中的动物数据行。行)
{
int worstMood=10;//超级快乐!
DataTable friendRecords=选择动物朋友((int)Animal[“AnimalID]”);
foreach(friendRecords.Rows中的DataRow friend)
{
DataTable animalFriends=选择_AnimalFriend((int)friend[“AnimalID_friend”);
foreach(animalFriends.Rows中的DataRow animalFriend)
{
int animalMood=获得动物的情绪((int)animalFriend[“情绪”);
if(动物性<苦艾)
{
艾草=动物性植物;
}
}
}
}
但这将不起作用,因为动物表不按顺序遵循已形成的动物朋友层次结构。动物可以在任何时候交朋友!所以动物(1)可能有动物(4000)作为朋友。动物(1)不会显示准确的情绪,因为它会在动物(4000)的情绪更新之前检查动物(4000)的情绪。每天都有新的动物被丢弃。我想这个解决方案可能是一个普通的算法设计,但我一直没能找到它。我不相信我有正确的术语来准确地搜索它
非常感谢,如果这个问题已经得到了回答,那么很抱歉
添加:
下面是犹太人区可能的关系图表:
反社会动物处于底层,没有属于它们的朋友。正常的动物到处都是。正常的动物友谊没有确切的结构,除非(正如塞巴斯蒂安指出的)不可能有一个闭环(如果设计正确的话)
每周将增加数十万只动物,处理速度是一个关键因素 问得好。所以,如果我理解正确的话,你们基本上有带圈的有向图。您可以将每个动物都视为一个节点(顶点),该节点具有其情绪所依赖的动物的传出边,以及其情绪所影响的动物的传入边。显然,反社会动物只会有来袭的边缘 如果你这样想,你会注意到两件事 1) 你可以设计一个迭代算法,扫描所有动物,检查每只动物是否有任何向外的边缘,只针对它的社交或已经处理的动物。如果是,我们计算动物的情绪,并将其标记为已处理。如果没有,我们就跳过这个迭代 2) 因为您的图中可以有循环,所以此算法不会总是完成。也就是说,你可以让动物A依赖于B,B依赖于C,C依赖于A。如果你有简单的逻辑,比如在你的例子中,最低情绪获胜,你可能会通过分配给循环中的所有动物来检测和解决这些循环-在这种情况下,A,B,C最低共同情绪
希望有帮助 有趣的问题。如果我理解正确的话,每只动物的幸福是所有动物幸福的最小值,如果它是单向的朋友(入境) 如果是这样的话,那么挑战在于每一只动物的朋友的幸福都取决于他们的朋友,依此类推,从哪里开始呢 这是我第一眼看到的 因为每天都会有新的动物出现,所以你需要每天重新开始,并且你需要从快乐程度最低的动物开始。很容易找到它们,然后把快乐传播给所有它们是朋友的动物,相应地调整它们的快乐水平。然后取所有调整后的动物,重复上述步骤,直到不再调整动物。一旦这个快乐水平被完全传播,移动到下一个最高的快乐水平并重复,直到剩下的最高快乐水平被处理 有趣的是,哪种动物(如果有的话)是反社会的并不重要。它们只是没有影响输入的动物,因此不会被这个过程调整 我认为这会让你达到你想要的目的,编写代码应该一点也不困难
希望能有所帮助。首先抓起所有反社会的动物,从最不快乐的动物到最快乐的动物。将所有群居动物的幸福感初始化为最大值(这使一切变得更容易,因为你不必检测以前不幸福的动物何时变得更幸福)。然后,只需在列表上迭代,并将快乐水平传播到友谊链上:
void UpdateFarm()
{
// Start with a list of antisocial animals from least to most happy.
var antisocialAnimals = GetAntisocialAnimals().OrderBy(x => x.Happiness);
// Initialise the social animals to the global maximum. Note the
// global maximum is the happiest antisocial animal. This is done to
// avoid the case where an antisocial animal's happiness has increased,
// so some of the social animals are too unhappy.
var maxHappiness = antisocialAnimals.Last().Happiness;
var socialAnimals = GetSocialAnimals();
foreach (var socialAnimal in socialAnimals)
socialAnimal.Happiness = maxHappiness;
// Now iterate from least to most happy, propagating up the friend chain.
foreach (var antisocialAnimal in antisocialAnimals)
UpdateFriends(antisocialAnimal);
}
// To propagate a happiness change, we just find all friends with a higher
// happiness and then lower them, then find their friends and so on.
void UpdateFriends(Animal animal)
{
var friends = GetFriends(animal); // Friends with this animal, not friends of.
foreach (var friend in friends.Where(x => x.Happiness > animal.Happiness))
{
friend.Happiness = animal.Happiness;
// Since this friend's happiness has changed, we now need to update
// its friends too.
UpdateFriends(friend);
}
}
- 如果反社会动物的情绪是绝对最低的,那么它的所有朋友和朋友的朋友都会继承它压倒一切的坏情绪李>
- 如果反社会动物的情绪处于绝对最低的第二位,那么它的所有朋友和朋友的朋友都将继承它的情绪,前提是他们还不是绝对最低情绪动物的朋友/朋友
void UpdateFarm()
{
// Start with a list of antisocial animals from least to most happy.
var antisocialAnimals = GetAntisocialAnimals().OrderBy(x => x.Happiness);
// Initialise the social animals to the global maximum. Note the
// global maximum is the happiest antisocial animal. This is done to
// avoid the case where an antisocial animal's happiness has increased,
// so some of the social animals are too unhappy.
var maxHappiness = antisocialAnimals.Last().Happiness;
var socialAnimals = GetSocialAnimals();
foreach (var socialAnimal in socialAnimals)
socialAnimal.Happiness = maxHappiness;
// Now iterate from least to most happy, propagating up the friend chain.
foreach (var antisocialAnimal in antisocialAnimals)
UpdateFriends(antisocialAnimal);
}
// To propagate a happiness change, we just find all friends with a higher
// happiness and then lower them, then find their friends and so on.
void UpdateFriends(Animal animal)
{
var friends = GetFriends(animal); // Friends with this animal, not friends of.
foreach (var friend in friends.Where(x => x.Happiness > animal.Happiness))
{
friend.Happiness = animal.Happiness;
// Since this friend's happiness has changed, we now need to update
// its friends too.
UpdateFriends(friend);
}
}
public void MoodCalculator()
{
/** Reasoning:
*
* The unidirectional cyclic graph can be also expressed as multiple friend
* trees where
* anti-social animal is the root node of a friend tree. Because a social animal's
* mood is that of its lowest mood friend this means that regardless of the
* tree depth of an animal
* it's mood is that of the mood of the lowest mood antisocial animal
* who's tree it is a member of.
*
* */
SortedList<int, List<Animal>> moodGroups = new SortedList<int, List<Animal>>();
HashSet<Animal> allAnimals = new HashSet<Animal>();
//get all antisocial animals and group according to mood
//work from low to high mood
forach(Animal a in GetAllAntiSocialAnimalsFromDb())
{
if(!moodGroups.ContainsKey(a.Mood)) moodGroups.Add(a.Mood, new List<Animal>());
moodGroups[a.Mood].Add(a);
}
foreach(var item in moodGroups)
{
//add our root antisocial animals to master group
foreach(Animal a in item.Value) allAnimals.Add(a);
//recurse over tree starting at antisocial animal roots
TreeRecurse(item.Value, allAnimals, item.Key);
}
}
public void TreeRecurse(List<Animal> children, List<Animal> allAnimals, int mood)
{
//can look for list as we are just grouping everything and don't care about tree
//structure
//db call should only get unique/distinct animals
List<Animal> parentAnimals = GetParentAnimalsOfChildAnimalListFromDb(children);
//remove animals from from parents if they are already in the allAnimal set
//working from low mood to high we can ignore animals that have appeared in a
//lower mood tree
parentAnimals.RemoveAll(a => allAnimals.Contains(a));
//add animals to allAnimals and set mood
foreach (Animal a in parentAnimals)
{
a.Mood = mood;
allAnimals.Add(a);
}
//end recurse
if (parentAnimals.Count == 0) return;
//recurse
else TreeRecurse(parentAnimals, allAnimals, mood);
}