Какой алгоритм я должен использовать, чтобы максимизировать количество задач (со сроками), которые я могу сделать? - PullRequest
0 голосов
/ 12 апреля 2020

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

| task | valid from | valid until |
|------|------------|-------------|
| t01  | 1          | 3           |
| t02  | 2          | 2           |
| t03  | 1          | 1           |
| t04  | 2          | 3           |
| t05  | 2          | 3           |

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

Обновление

на основе комментариев, которые я написал код, он работает, но все еще не имеет хорошей производительности с огромным количеством задач.

public static int countTodoTasks(int[] validFrom, int[] validUnitil)
{
           var tasks = new List<TaskTodo>();
           for (int i = 0; i < validFrom.Length; i++)
           {
               tasks.Add(new TaskTodo { ValidFrom = validFrom[i], ValidUntil = validUnitil[i] });
           }
           tasks = tasks.OrderBy(x => x.ValidUntil).ToList();
           var lDay = 0;
           var schedule = new Dictionary<int, TaskTodo>();
           while (tasks.Count > 0)
           {
               lDay = findBigestMinimumOf(lDay, tasks[0].ValidFrom, tasks[0].ValidUntil);
               if (lDay != -1)
               {
                   schedule[lDay] = tasks[0];
               }
               tasks.RemoveAt(0);
               tasks.RemoveAll(x => lDay >= x.ValidUntil);
           }
           return schedule.Count;
       }

static int findBigestMinimumOf(int x, int start, int end)
{
        if (start > x)
           {
               return start;
           }

           if ((x == start && start == end) || x == end || x > end)
           {
               return -1;
           }
           return x + 1;
}

Ответы [ 2 ]

1 голос
/ 14 апреля 2020

Если задачи имеют одинаковую длительность, используйте жадный алгоритм, как описано выше. Если он слишком медленный, используйте индексы (= хэширование) и инкрементный расчет , чтобы ускорить его, если вам нужно уменьшить масштаб.

  • Индексация: во время настройки итерируйте все задачи, чтобы создать карту (= словарь?), которая отображает каждую дату выполнения в список задач. Более того, используйте NavigableMap (TreeMap), чтобы вы могли запросить конечный итератор (все задачи, начиная с указанной даты выполнения c, по порядку). Затем жадный алгоритм может использовать это для лучшего масштабирования (представьте лучшую запись bi gO).
  • Инкрементный расчет: вычисляйте только дельты для каждой рассматриваемой задачи.

Если задачи имеют различную длительность, жадный алгоритм (он же строительный heuristi c) не даст вам оптимального решения. Тогда это NP-трудно. После Construction Heuristi c (= жадный алгоритм) запустите локальный поиск (например, поиск по Tabu). Такие библиотеки, как OptaPlanner (к сожалению, Java, а не C# - ищите альтернативы) могут сделать для вас оба.

Также обратите внимание, что существует множество жадных алгоритмов go. (Первая подгонка, пригонка подгонки, ...)

0 голосов
/ 13 апреля 2020

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

  1. Выберите минимальное "действительное из", разумно.
  2. Добавить в Xcandidates все кандидаты с «valid from» = minday.
  3. Если Xcandidates go до 1.
  4. не выбран, выберите интервал x, из Xcandidates, с самым ранним «validable до».
  5. Удалите x, вставив его в свое расписание.
  6. Удалите все Xcandidates с "действительным до" = разум.
  7. Увеличивайте разум и go до 2.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...