回溯算法 - 试图找到更好的解决方案

发布于 2025-01-24 15:14:46 字数 5217 浏览 0 评论 0原文

我想在我目前正在从事的项目中寻求一些帮助,我应该在这里使用回溯来创建一种“组织程序”。

这个故事是,我有一定数量的动物,每只动物都有自己的类型,栖息地和属性。我还列出了整数列表,其中包括所有可能的笼子大小可以放入。在每个笼子大小中,我可以创建一个无限数量的实际笼子。只要它们的大小小于或等于笼子的大小,就可以将两只(或更多)动物保存在相同的笼子中,并且它们是相同类型的(例如哺乳动物)或共享相同的栖息地(例如土地)。

我的算法应该将它们整理成笼子,以便最后,我得到了一个笼子清单,所有动物都放置了所有动物,并且使用了最少的笼子。

为了说明,假设我们有3只动物,两只猫(哺乳动物,土地,3个)和一个秃鹰(鸟,空气,4),我们可能的笼子大小为3、5、7。显然,只是看着在此示例中,我们可以看到,虽然猫可以在同一笼子中,但秃鹰将不可避免地会自行着陆,因此使用最少的笼子显然是2。猫; 5:秃鹰}或{7:猫,猫; 7:秃鹰}。

我最初通过递归设置回溯算法的方式是:

  • n :动物总数(在上面的示例中,这将是3
  • m :可以用来创建我们的笼子的数字列表(同样,这是三个)
  • r :我正在考虑使用给出的尺寸创建一个空的列表,但是目前我只是直接使用整数
  • e :当前周期的解决方案
  • opt :到目前为止,每当一个周期的e包含的笼子少于opt时,可以保存的最佳场景 新的

  • 作为
  • 检查 可以适合以前的任何一个笼子,因为仍然有足够的空间,并且可以将其与所有其他动物一起放置在同一笼子里

。首先检查它们是否可以自己安装,如果是,它还可以检查是否可以将其放在以前的笼子中。如果不能,它将创建一个新的笼子并添加动物,然后将笼子添加到E中,但是如果可以将其放入先前的笼子中,它将做得很多。

显然,这并不是很好。我向我的TA寻求一些帮助,他建议我考虑以下内容:

  • n :动物数量
  • m :n减去水平,这意味着随着我的移动越来越多在内部,我将无需放置一定数量的动物。因此,例如,在第一级,我仍然需要放置3只动物,而仅在第二层,而最终级别仅1。
  • r :笼子里的动物(?我没有t非常了解他在这里的意思,他的更深入的解释也没有帮助)
  • e :笼子清单,与上述
  • f1 相同:检查动物是否可以是放在给定的笼子中,以及它是否可以与
  • f2

中 的所有其他动物保持在一起说,我目前无法完全掌握他的解决方案,尽管我的确实在一定程度上有缺陷(例如,它仅检查可以放置动物的第一个可能的笼子,而无需检查所有其他可能性)。 我要在这里复制我的代码,目前看起来像这样,但是老实说,我更多地在寻找(和/或理解)更好的解决方案时寻求帮助。

对不起,这太长了,我可能会过度思考/过度解释这一点,但是在这个阶段我感到非常拼命哈哈。任何帮助将不胜感激!

public virtual void Trial(int level, ref CageList<Cage> E, ref CageList<Cage> OPT, ref bool found)
        {
            int i = -1;

            while (i < M[level]-1)
            {
                i++;
                ListObj<int> R_obj = R.FindIndex(i);


                if (f1(szint, R_obj))
                {
                    int k = 0; 

                    if (E.head == null)
                    {
                        AddFirsttoE(level, R_obj, ref E);
                    }
                    else
                    {
                        while (k < E.Count() && !f2(level, E.FindIndex(k), k, ref E, R_obj))            
                        {
                            k++;
                        }
                    }


                    if (level == N - 1)
                    {
                        if(!found || E.Count() < OPT.Count())
                        {
                            OPT = E;
                        }
                        found = true;
                    }
                    else
                    {
                        Trial(level + 1, ref E, ref OPT, ref found);
                    }
                }
                freeE(level, ref E);
            }
        } 

我的其他两个功能是:

public override bool f1(int level, ListObj<int> obj)
        {

            bool ret = false;
            ListaObj<Animal> test = Animals.FindIndex(level);

            if (((int)test.Content.Size).CompareTo(obj.Content) <= 0)
            {
                ret = true;
            }
            return ret;
        }
public override bool f2(int level, ListObj<Cage> obj, int level2, ref CageList<Cage> E, ListObj<int> empty_size)
        {
            bool ret = false;
            ListObj<Animal> test = Animals.FindIndex(level);
            bool can_keep_together = true;

            if (((int)test.Content.Size).CompareTo(obj.Content.CageSize) <= 0)  
            {
                AnimalList<Animal> caged = obj.Content.Animals;
                ListObj<Animal> p = caged.head;

                while (p != null && can_keep_together)                                   
                {
                    if (!p.Content.CanKeepTogether(test.Content))
                    {
                        can_keep_together = false;
                    }
                    p = p.Next;
                }

                if (can_keep_together)  
                {
                    ret = true;
                    obj.Content.Animals.Add(test.Content);
                    obj.Content.CageSize -= (int)test.Content.Size;
                }
            }
            else if (level2 == E.Count() - 1)  
            {
                ret = true;
                AnimalList<Animal> new_animal_list = new AnimalList<Animal>();
                new_animal_list.Add(test.Content);
                Cage new_cage = new Cage(empty_size.Content, new_animal_list);
                new_cage.CageSize -= (int)test.Content.Méret;
                E.Add(new_cage);
            }

            if (!can_keep_together && level2 == E.Count()-1)
            {
                ret = true;
                AnimalList<Animal> new_animal_list = new AnimalList<Animal>();
                new_animal_list.Add(test.Content);
                Cage new_cage = new Cage(empty_size.Content, new_animal_list);
                new_cage.CageSize -= (int)test.Content.Méret;
                E.Add(new_cage);
            }
            return ret;
        }

I’d like to ask for a little bit of help with a project I’m currently working on, where I’m supposed to create a sort of “organizing program” using backtracking.

The story is, I have a given number of animals, each with their own type, habitat, and size as attributes. I’m also given a list of integers, which includes all the possible cage sizes these animals can be placed into. Of each cage size, I can create an infinite number of actual cages. Two (or more) animals can be kept in the same cage for as long as the sum of their size is less than or equal to that of the size of the cage, and they are either the same type (mammals for example) or share the same habitat (e.g. land).

My algorithm is supposed to sort them into cages so that at the end, I get a list of cages with all animals placed and using the fewest possible cages.

To illustrate, let’s say we have 3 animals, two cats (mammal, land, 3) and a vulture (bird, air, 4), and our possible cage sizes have been given as 3, 5, 7. Obviously, just by looking at this example, we can see that while the cats can be in the same cage, the vulture will inevitably land in its own, so the fewest possible cages to use is obviously going to be 2. This can either be {7: cat, cat; 5: vulture} or {7: cat, cat; 7: vulture}.

The way I had initially though of setting up my backtrack algorithm through recursion was the following:

  • N: total number of animals (in the above example, this would be 3
  • M: a list of numbers that can be used to create our cages (again, this would be three)
  • R: I was thinking of creating a list empty cages here, using the sizes that were given, but for now I just straight up used the integers
  • E: the current cycle’s solution
  • OPT: the best possible scenario so far, whenever a cycle’s E contains fewer cages than the OPT, that gets saved as the new OPT.

two levels of check

  • f1: to check if the given animal can fit in the given cage, if it is empty
  • f2: to check if the given animal could fit in any of the previous cages, given that there is still enough room and that it can be placed in the same cage with all other animals.

This way, the algorithm would first take an animal, and go through all available cage sizes, checking first if they can fit by themselves, and if yes, it’ll also check whether it could be placed in a previous cage. If it can’t, it’ll create a new cage and add the animal, then add the cage to E, but if it can be placed into a previous cage, it will do as much.

Obviously, this isn’t working just quite right. I asked my TA for some help, and he suggested I instead consider the following:

  • N: number of animals
  • M: N minus level, meaning that as I move more and more inward, I would have eliminated the need to place a certain number of animals. So for example, on the first level, I still need to place 3 animals, while on the second level only 2, and on the final level only 1.
  • R: Animals in cages (? I didn’t quite understand what he meant here, and his deeper explanations were of no help either)
  • E: list of cages, same as above
  • f1: to check whether the animal could be placed in the given cage, and whether it can be kept together with all other animals already in it
  • f2: to check whether it could have been placed in any of the other cages we put together

Now, as I said, I currently can’t fully grasp his solution, and although mine does work to a certain extent it does have its flaws (for example, it only checks for the first possible cage an animal could be placed into, without checking all other possibilities).
I’m gonna copy my code here, which currently looks like this, but honestly I’m more looking for some help in finding (and/or comprehending) a better solution.

Sorry this got so long-winded, I might be overthinking/overexplaining this but I'm feeling pretty desperate at this stage haha. Any help would be GREATLY appreciated!

public virtual void Trial(int level, ref CageList<Cage> E, ref CageList<Cage> OPT, ref bool found)
        {
            int i = -1;

            while (i < M[level]-1)
            {
                i++;
                ListObj<int> R_obj = R.FindIndex(i);


                if (f1(szint, R_obj))
                {
                    int k = 0; 

                    if (E.head == null)
                    {
                        AddFirsttoE(level, R_obj, ref E);
                    }
                    else
                    {
                        while (k < E.Count() && !f2(level, E.FindIndex(k), k, ref E, R_obj))            
                        {
                            k++;
                        }
                    }


                    if (level == N - 1)
                    {
                        if(!found || E.Count() < OPT.Count())
                        {
                            OPT = E;
                        }
                        found = true;
                    }
                    else
                    {
                        Trial(level + 1, ref E, ref OPT, ref found);
                    }
                }
                freeE(level, ref E);
            }
        } 

while my two other functions are:

public override bool f1(int level, ListObj<int> obj)
        {

            bool ret = false;
            ListaObj<Animal> test = Animals.FindIndex(level);

            if (((int)test.Content.Size).CompareTo(obj.Content) <= 0)
            {
                ret = true;
            }
            return ret;
        }
public override bool f2(int level, ListObj<Cage> obj, int level2, ref CageList<Cage> E, ListObj<int> empty_size)
        {
            bool ret = false;
            ListObj<Animal> test = Animals.FindIndex(level);
            bool can_keep_together = true;

            if (((int)test.Content.Size).CompareTo(obj.Content.CageSize) <= 0)  
            {
                AnimalList<Animal> caged = obj.Content.Animals;
                ListObj<Animal> p = caged.head;

                while (p != null && can_keep_together)                                   
                {
                    if (!p.Content.CanKeepTogether(test.Content))
                    {
                        can_keep_together = false;
                    }
                    p = p.Next;
                }

                if (can_keep_together)  
                {
                    ret = true;
                    obj.Content.Animals.Add(test.Content);
                    obj.Content.CageSize -= (int)test.Content.Size;
                }
            }
            else if (level2 == E.Count() - 1)  
            {
                ret = true;
                AnimalList<Animal> new_animal_list = new AnimalList<Animal>();
                new_animal_list.Add(test.Content);
                Cage new_cage = new Cage(empty_size.Content, new_animal_list);
                new_cage.CageSize -= (int)test.Content.Méret;
                E.Add(new_cage);
            }

            if (!can_keep_together && level2 == E.Count()-1)
            {
                ret = true;
                AnimalList<Animal> new_animal_list = new AnimalList<Animal>();
                new_animal_list.Add(test.Content);
                Cage new_cage = new Cage(empty_size.Content, new_animal_list);
                new_cage.CageSize -= (int)test.Content.Méret;
                E.Add(new_cage);
            }
            return ret;
        }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文