реализация алгоритма дерева c # - PullRequest
2 голосов
/ 02 мая 2011

У меня есть некоторые проблемы, решающие алгоритм, используемый для поиска всех возможных комбинаций, берущих элементы из N списков различий (где N> = 2 && N <= 7 -> это число является фиксированным, и я могу сделать разные методы для каждого N),Проблема заключается в следующем: у меня есть пять словарей:

IDictionary<int, MyEnum> listOne; 
IDictionary<int, MyEnum> listTwo;
IDictionary<int, MyEnum> listThree;
IDictionary<int, MyEnum> listFour;
IDictionary<int, MyEnum> listN;

enum MyEnum
    {
    MyEnumOne,
    MyEnumTwo,
    MyEnumThree,
    MyEnumFour,
    MyEnumFive,
    MyEnumOther
   }

, которые могут иметь любое количество элементов (не более 100, и большую часть времени они будут иметь от 32 до 64 элементов) и где MyEnumявляется простым перечислением имен с некоторыми значениями.

Для каждой возможной комбинации у меня есть метод, который проверяет комбинацию и проверяет, удовлетворяет ли она некоторым условиям, и если они удовлетворены, хранит некоторые данные, основанные на комбинации.

Я пробовал простые вложенные итерации с использованием foreachs для каждого списка, что, как и ожидалось, требует выполнения эонов!

Любая помощь, как с того, где я должен начать, что мне делать, или событие, что яне следует делать, будет приветствоваться !, также, если требуется дополнительная информация, пожалуйста, не стесняйтесь спрашивать!

** РЕДАКТИРОВАТЬ: комбинация, основанная на пяти списках, как показано ранее, будетбыть, например:

(MyEnumOne, MyEnumOne, MyEnumFour, MyEnumFive, MyEnumTwo)

и, поскольку эта комбинация, может появляться несколько раз (так как значение MyEnumOne может быть много раз в listOne и т. д.), я должен также,вести учет того, сколько раз эта комбинация происходит.

Ответы [ 2 ]

1 голос
/ 02 мая 2011

Вы можете легко решить подобные проблемы с помощью LINQ.

var solutions = from pair1 in listOne
                where IsCandidate(pair1)
                from pair2 in listTwo
                where IsCandidate(pair1, pair2)
                from pair3 in listThree
                where IsCandidate(pair1, pair2, pair3)
                from pair4 in listFour
                where IsCandidate(pair1, pair2, pair3, pair4)
                from pair5 in listFive
                where IsCandidate(pair1, pair2, pair3, pair4, pair5)
                from pair6 in listSix
                where IsCandidate(pair1, pair2, pair3, pair4, pair5, pair6)
                from pair7 in listSeven
                where IsSolution(pair1, pair2, pair3, pair4, pair5, pair6, pair7)
                select new { pair1, pair2, pair3, pair4, pair5, pair6, pair7 };

Конечно, этот подход действителен только потому, что число списков известно во время компиляции.Альтернативный подход заключается в том, чтобы иметь общий способ построения возможных комбинаций, как Эрик Липперт показывает в своем посте .

Все эти промежуточные звенья where во всем запросе должны фильтроваться.как можно быстрее выводить недопустимые комбинации.

РЕДАКТИРОВАТЬ

Исправлено решение, позволяющее эффективно подсчитывать, сколько раз встречается одна и та же комбинация, игнорируя ключи исходного источника.

Чтобы добиться этого, я собираюсь применить преобразование к каждому словарю.Я собираюсь преобразовать каждый словарь в новый словарь, где ключом будет значение перечисления, а значением будет количество раз, когда значения перечисления происходят в исходном словаре.

IDictionary<MyEnum, int> CountOccurrences(IEnumerable<MyEnum> values)
{
    return (from e in values group e by e).ToDictionary(grp => grp.Key, grp => grp.Count());
}

var solutions = from p1 in CountOccurrences(listOne.Values)
                where IsCandidate(p1)
                from p2 in CountOccurrences(listTwo.Values)
                where IsCandidate(p1, p2)
                from p3 in CountOccurrences(listThree.Values)
                where IsCandidate(p1, p2, p3)
                from p4 in CountOccurrences(listFour.Values)
                where IsCandidate(p1, p2, p3, p4)
                from p5 in CountOccurrences(listFive.Values)
                where IsCandidate(p1, p2, p3, p4, p5)
                from p6 in CountOccurrences(listSix.Values)
                where IsCandidate(p1, p2, p3, p4, p5, p6)
                from p7 in CountOccurrences(listSeven.Values)
                where IsSolution(p1, p2, p3, p4, p5, p6, p7)
                select new {
                    E1 = p1.Key,
                    E2 = p2.Key,
                    E3 = p3.Key,
                    E4 = p4.Key,
                    E5 = p5.Key,
                    E6 = p6.Key,
                    E7 = p7.Key,
                    Times = p1.Value * p2.Value * p3.Value * p4.Value * p5.Value * p6.Value * p7.Value
                };
0 голосов
/ 02 мая 2011

Как правило, с такими проблемами вы должны попытаться построить решения, а не слепо проходить все пространство поиска в поисках их.

Я предполагаю, что вам действительно нужно сделать следующее: - у вас есть N списков, каждый из которых имеет L (I) элементов. - вы хотите сгенерировать все комбинации длины N, где первый элемент происходит из первого списка, второй элемент из второго списка и т. д.

Кажется, нет никакого способа избежать сложного сочетания всех комбинаций. Все 100 элементов ^ N ~ 10 ^ 14 ... которые займут эоны.

Я второй запрос на небольшие образцы и условия, которые должны быть удовлетворены.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...