Q:

Minimum Agents required for delivering product in warehouse

Problem statement:
I have a list of WareHouses. WareHouse has two properties i.e. openingTime, closingTime.
public class WareHouse {

  private int startTime;
  private int endTime;
}

There are group of Agents whose responsibility is to deliver product to Warehouse,I need to calculate minimum number of Agents required who can deliver products to all warehouses.
Assumption: when a agent is delivering product to a particular warehouse say W1{1,2} he can only come out after a duration of 1 hour i.e closing time of warehouse.

Warehouse{openingTime, closingTime}
  w1{1,2},w2{2,4},w3{3,6},w4{9,11},w5{10,11}

public static void main(String[] args) {

    WareHouse w1 = new WareHouse(2, 4);
    WareHouse w2 = new WareHouse(1, 2);
    WareHouse w3 = new WareHouse(3, 6);
    WareHouse w4 = new WareHouse(10, 11);
    WareHouse w5 = new WareHouse(9, 11);
    List<WareHouse> wareHouses = new ArrayList<WareHouse>();
    wareHouses.add(w1);
    wareHouses.add(w2);
    wareHouses.add(w3);
    wareHouses.add(w4);
    wareHouses.add(w5);
}

Ideally, it requires 2 agents, so how to design algorithm for it?
My approach:
There would be a background job that will check status of all agents. Once a agent picks up a task , i will set it’s availability to false. Once it finished i will add him back to agent queue. However, my main challenge here is how to guess that agent has completed task, how can i simulate this event this will tell me task is over and it’s been 2 hours?

A:

To calculate minimum number of agents, you don't need to simulate the delivery process. It's an interval partitioning problem and you can use a greedy algorithm. Look into https://www.cs.princeton.edu/~wayne/kleinberg-tardos/pearson/04GreedyAlgorithms-2x2.pdf.
In your case, you may use the following agent class (you'll need getters for Warehouse variables since they are private - I didn't show that here):
public class Agent {
   int lastFinishTime;

   boolean isCompatibleWith(WareHouse x) {
      return x.startTime > lastFinishTime;
   }

   boolean scheduleWareHouse(WareHouse x) {
      lastFinishTime = x.endTime;
   }
}

You can then apply the interval partitioning algorithm as follows (while using a priority queue of agents, sorted based on lastFinishTime):
Sort warehouses by starting time so that s1 ≤ s2 ≤ ... ≤ sn.
d ← 0
for j = 1 to n {
 if (warehouse j is compatible with some agent k)
 schedule warehouse j to agent k
 else
 allocate a new agent d + 1
 schedule warehouse j to agent d + 1
 d ← d + 1
}

Complete implementation:
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.PriorityQueue;

public class Partition {

    public static class WareHouse {

          int startTime;
          int endTime;

          public WareHouse(int i, int j) {
              startTime=i;
              endTime=j;
          }
    }

    public static class Agent {
        int end;

        public Agent() {

        }

        public boolean isCompWith(WareHouse x) {
            return end <=x.startTime;
        }

        public void schedule(WareHouse x) {
            end=x.endTime;
        }

    }

    public static void main(String...args) {
        WareHouse w1 = new WareHouse(2, 4);
        WareHouse w2 = new WareHouse(1, 2);
        WareHouse w3 = new WareHouse(3, 6);
        WareHouse w4 = new WareHouse(10, 11);
        WareHouse w5 = new WareHouse(9, 11);
        List<WareHouse> wareHouses = new ArrayList<WareHouse>();
        wareHouses.add(w1);
        wareHouses.add(w2);
        wareHouses.add(w3);
        wareHouses.add(w4);
        wareHouses.add(w5);
        Collections.sort(wareHouses, new Comparator<WareHouse> (){
            public int compare(WareHouse x, WareHouse y) {
                return x.startTime - y.startTime;
            }
        });
        PriorityQueue<Agent> queue = 
                new PriorityQueue<Agent>(new Comparator<Agent>() {
                    public int compare(Agent x, Agent y) {
                        return x.end- y.end;
                    }
                });
        for(WareHouse x: wareHouses) {
            Agent a = queue.poll();
            if(a==null) {
                a=new Agent();
                a.schedule(x);
                queue.add(a);
            } 
            else if (a.isCompWith(x)) {
                a.schedule(x);
                queue.add(a);
            } else {
                Agent b = new Agent();
                b.schedule(x);
                queue.add(a);
                queue.add(b);
            }
        }
        System.out.println(queue.size());
    }

