Activity selection problem | Greedy

Scheduling multiple activities with shared resources, the goal is to select the largest set of activities compatible with each other.

There is a set of n activities S = {a1, a2, ..., an}, and each activity has a start time si and an end time fi. Activities that do not overlap with each other in time periods are compatible with each other, and a subset of the largest compatible activities is selected.


1. Algorithm idea

It is recorded \bg_white S_k=\left \{ a_i\epsilon S|s_i>f_k \right \}as the set of tasks that start after the end of ak, and obviously has the following theorem:

Theorem 1: Consider an arbitrary non-empty question S_k, so that a_mis S_kthe end of the oldest activity, a_min S_kthe event of a maximum compatible subset,

First, the time period of each activity should be sorted according to the end time (increasing order). 

Intuitively, we should select such an activity every time, and the remaining resources after selecting it should be used by as many other tasks as possible. Therefore, a greedy choice is drawn : each time the activity that is compatible with the subset is selected and ended earlier, it is added to the subset. Known from Theorem 1: This result must be a subset of the largest compatible activity (not unique).


Two, algorithm implementation

1. Recursive implementation

#define MAXN
bool isSelected[MAXN] = {false};   //标记是否加入最终的子集

/* 开始时间与结束时间对应存储在数组s、f中(已经按结束时间增序排序好)
 * 在第 k + 1 ~ n个活动间选择:子问题大小为 Sk 
 * 选取结果存储在 isSelected 数组中*/
void RecursiveActivitySelector(int s[], int f[], int k, int n) {
    int m = k + 1;   //开始寻找活动的起点
    while (m <= n && s[m] < f[k])
        m++;   //在范围内找到合适的 m
    if (m <= n) {
        isSelected[m] = true;  //选择第 m个活动
        RecursiveActivitySelector(s, f, m, n);
    }
}

2. Recursive realization 

#define MAXN
bool isSelected[MAXN] = {false};   //标记是否加入最终的子集
/* 开始时间与结束时间对应存储在数组s、f中(已经按结束时间增序排序好)
 * 活动个数为 n
 * 选取结果存储在 isSelected 数组中 */
void GreedyActivitySelector(int s[], int f[], int n) {
    int temp = 1;  //当前选取的活动
    isSelected[temp] = true;
    for(int i = 2; i <=n; i++) {
        /* 找到合适的 */
        if(s[i] >= f[temp]) { 
            temp = i;  //选择
            isSelected[temp] = true;
        }
    }
}

Three, other

There is a set of n activities S = {a1, a2, ..., an}, and each activity has a start time si and an end time fi. We need to arrange them in some classrooms. How many classrooms are required at least?


Idea 1: Greedy algorithm

       This question is an extension of the above question. You can select a subset of the largest compatible activities in S (equivalent to assigning them to a classroom), and then remove these selected activities from S, continue to choose... Until all activities in S are selected, just see how many classrooms are allocated.


Idea 2: Simulation algorithm

      Directly simulate the usage of the classroom: put the start time s and end time f together in increasing order, and the end time has a higher priority (when the time is the same, the end time is ranked before the start time). Traverse this sorted time point in turn, classroom++ when you encounter the start time, and classroom-- when you encounter the end time. Maintain a max_classroom in the middle, record the maximum value of the classroom, which is the final answer.

 

Guess you like

Origin blog.csdn.net/weixin_43787043/article/details/105412113