-1

I have many tasks, each task defined by the day that I can start working on and the last day that task is still valid to do, each task done withing one day, not more, I can do one task per day. The tasks with the deadlines as described in the below table.

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

the number of tasks may be a huge number. I want to know which algorithm I can use to solve this problem to maximize the number of tasks that I can do.

Update

base on the comments I wrote this code it is working but still hasn't good performance with a huge number of tasks.

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;
}
Henka Programmer
  • 727
  • 7
  • 25
  • You can use greedy algorithm. The idea is to always try to insert the task with the earliest deadline into your schedule. You can read extended explanation of idea [here](https://en.wikipedia.org/wiki/Interval_scheduling#Greedy_polynomial_solution) – Dzianis Karpuk Apr 12 '20 at 20:57
  • For your update: `tasks.RemoveAt(0)` and `tasks.RemoveAll(...)` are intoducing `O(n)` timecomplexity (so making the whole thing `O(n^2)`). Since the `tasks` are ordered just keep a pointer and instead of removing tasks move the pointer forward untill you find the next task that has a valid deadline –  Apr 12 '20 at 21:44

2 Answers2

1

If the tasks have the same duration, then use a greedy algorithm as described above. If it's too slow, use indexes (= hashing) and incremental calculation to speed it up if you need to scale out.

  • Indexing: during setup, iterate through all tasks to create map (=dictionary?) that maps each due date to a list of tasks. Better yet, use a NavigableMap (TreeMap), so you can ask for tail iterator (all tasks starting from a specific due date, in order). The greedy algorithm can then use that to scale better (think a better bigO notation).
  • Incremental calculation: only calculate the delta's for each task you're considering.

If the tasks have different duration, a greedy algorithm (aka construction heuristic) won't give you the optimal solution. Then it's NP-hard. After the Construction Heuristic (= greedy algorithm), run a Local Search (such as Tabu Search). Libraries such as OptaPlanner (Java, not C# unfortunately - look for alternatives there) can do both for you.

Also note there are multiple greedy algo's (First Fit, Fit Fit Decreasing, ...)

Geoffrey De Smet
  • 26,223
  • 11
  • 73
  • 120
0

I suppose you can apply greedy algorithm for you purpose in this way.

  1. Select minimal "valid from", minday.
  2. Add to Xcandidates, all candidates with "valid from" = minday.
  3. If no Xcandidates go to 1.
  4. Select the interval, x, from Xcandidates, with earliest "valid until".
  5. Remove x, inserting it in your schedule.
  6. Remove all Xcandidates with "valid until" = minday.
  7. Increment minday and go to 2.