0% found this document useful (0 votes)
108 views

Greedy Algorithm - Activity-Selection-Problem & Optimal Merge Pattern

The Activity Selection Problem involves selecting the maximum number of non-conflicting activities that can be executed by a single resource within a given time frame. It is modeled as an optimization problem and solved using a greedy algorithm. The algorithm sorts activities by finish time and sequentially selects activities whose start time is greater than or equal to the finish time of the previously selected activity. This yields the optimal solution by greedily choosing activities that minimize idle time. The time complexity of the algorithm is O(n log n) in the worst case when initial sorting is required.

Uploaded by

John Webb
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
108 views

Greedy Algorithm - Activity-Selection-Problem & Optimal Merge Pattern

The Activity Selection Problem involves selecting the maximum number of non-conflicting activities that can be executed by a single resource within a given time frame. It is modeled as an optimization problem and solved using a greedy algorithm. The algorithm sorts activities by finish time and sequentially selects activities whose start time is greater than or equal to the finish time of the previously selected activity. This yields the optimal solution by greedily choosing activities that minimize idle time. The time complexity of the algorithm is O(n log n) in the worst case when initial sorting is required.

Uploaded by

John Webb
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 11

Activity Selection Problem

The Activity Selection Problem is an optimization problem which deals with the selection of
non-conflicting activities that needs to be executed by a single person or machine in a given
time frame.

Each activity is marked by a start and finish time. Greedy technique is used for finding the
solution since this is an optimization problem.

What is Activity Selection Problem?

Let's consider that you have n activities with their start and finish times, the objective is to
find solution set having maximum number of non-conflicting activities that can be
executed in a single time frame, assuming that only one person or machine is available for
execution.

Some points to note here:

 It might not be possible to complete all the activities, since their timings can collapse.
 Two activities, say i and j, are said to be non-conflicting if si >= fj or sj >= fi where si
and sj denote the starting time of activities i and j respectively, and fi and fj refer to the
finishing time of the activities i and j respectively.
 Greedy approach can be used to find the solution since we want to maximize the count of
activities that can be executed. This approach will greedily choose an activity with earliest
finish time at every step, thus yielding an optimal solution.

Input Data for the Algorithm:

 act[] array containing all the activities.


 s[] array containing the starting time of all the activities.
 f[] array containing the finishing time of all the activities.

Ouput Data from the Algorithm:

 sol[] array refering to the solution set containing the maximum number of non-
conflicting activities.

Steps for Activity Selection Problem

Following are the steps we will be following to solve the activity selection problem,

Step 1: Sort the given activities in ascending order according to their finishing time.
Step 2: Select the first activity from sorted array act[] and add it to sol[] array.

Step 3: Repeat steps 4 and 5 for the remaining activities in act[].

Step 4: If the start time of the currently selected activity is greater than or equal to the finish
time of previously selected activity, then add it to the sol[] array.

Step 5: Select the next activity in act[] array.

Step 6: Print the sol[] array.

Activity Selection Problem Example

Let's try to trace the steps of above algorithm using an example:

In the table below, we have 6 activities with corresponding start and end time, the objective is
to compute an execution schedule having maximum number of non-conflicting activities:

Start Time (s) Finish Time (f) Activity Name

5 9 a1

1 2 a2

3 4 a3

0 6 a4

5 7 a5

8 9 a6

A possible solution would be:

Step 1: Sort the given activities in ascending order according to their finishing time.

The table after we have sorted it:

Start Time (s) Finish Time (f) Activity Name

1 2 a2

3 4 a3

0 6 a4

5 7 a5
5 9 a1

8 9 a6

Step 2: Select the first activity from sorted array act[] and add it to the sol[] array, thus sol
= {a2}.

Step 3: Repeat the steps 4 and 5 for the remaining activities in act[].

Step 4: If the start time of the currently selected activity is greater than or equal to the finish
time of the previously selected activity, then add it to sol[].

Step 5: Select the next activity in act[]

For the data given in the above table,

A. Select activity a3. Since the start time of a3 is greater than the finish time of a2 (i.e. s(a3)
> f(a2)), we add a3 to the solution set. Thus sol = {a2, a3}.
B. Select a4. Since s(a4) < f(a3), it is not added to the solution set.
C. Select a5. Since s(a5) > f(a3), a5 gets added to solution set. Thus sol = {a2, a3, a5}
D. Select a1. Since s(a1) < f(a5), a1 is not added to the solution set.
E. Select a6. a6 is added to the solution set since s(a6) > f(a5). Thus sol = {a2, a3, a5, a6}.

Step 6: At last, print the array sol[]

Hence, the execution schedule of maximum number of non-conflicting activities will be:

(1,2) (3,4) (5,7) (8,9)

PROGRAM:

#include <bits/stdc++.h>

using namespace std;


#define N 6 // defines the number of activities

// Structure represents an activity having start time and finish time.


struct Activity
{
int start, finish;
};

// This function is used for sorting activities according to finish time


bool Sort_activity(Activity s1, Activity s2)
{
return (s1.finish< s2.finish);
}

/* Prints maximum number of activities that can


be done by a single person or single machine at a time.
*/
void print_Max_Activities(Activity arr[], int n)
{
// Sort activities according to finish time
sort(arr, arr+n, Sort_activity);

cout<< "Following activities are selected \n";

// Select the first activity


int i = 0;
cout<< "(" <<arr[i].start<< ", " <<arr[i].finish << ")\n";

// Consider the remaining activities from 1 to n-1


for (int j = 1; j < n; j++)
{
// Select this activity if it has start time greater than or equal
// to the finish time of previously selected activity
if (arr[j].start>= arr[i].finish)
{
cout<< "(" <<arr[j].start<< ", "<<arr[j].finish <<
") \n";
i = j;
}
}
}

int main()
{
Activity arr[N];
for(int i=0; i<=N-1; i++)
{
cout<<"Enter the start and end time of "<<i+1<<" activity
\n";
cin>>arr[i].start>>arr[i].finish;
}

print_Max_Activities(arr, N);
return 0;
}

The program is executed using same inputs as that of the example explained above. This will
help in verifying the resultant solution set with actual output.
Time Complexity Analysis

Following are the scenarios for computing the time complexity of Activity Selection
Algorithm:

 Case 1: When a given set of activities are already sorted according to their finishing time,
then there is no sorting mechanism involved, in such a case the complexity of the algorithm
will be O(n)
 Case 2: When a given set of activities is unsorted, then we will have to use the sort()
method defined in bits/stdc++ header file for sorting the activities list. The time complexity
of this method will be O(nlogn), which also defines complexity of the algorithm.

Real-life Applications of Activity Selection Problem

Following are some of the real-life applications of this problem:

 Scheduling multiple competing events in a room, such that each event has its own start and
end time.
 Scheduling manufacturing of multiple products on the same machine, such that each
product has its own production timelines.
 Activity Selection is one of the most well-known generic problems used in Operations
Research for dealing with real-life business problems.
Optimal Merge Pattern
Merge a set of sorted files of different length into a single sorted file. We need to find an
optimal solution, where the resultant file will be generated in minimum time.

If the number of sorted files are given, there are many ways to merge them into a single
sorted file. This merge can be performed pair wise. Hence, this type of merging is called as 2-
way merge patterns.

As, different pairings require different amounts of time, in this strategy we want to determine
an optimal way of merging many files together. At each step, two shortest sequences are
merged.

To merge a p-record file and a q-record file requires possibly p + q record moves, the
obvious choice being, merge the two smallest files together at each step.

Two-way merge patterns can be represented by binary merge trees. Let us consider a set of n
sorted files {f1, f2, f3, …, fn}. Initially, each element of this is considered as a single node
binary tree. To find this optimal solution, the following algorithm is used.

Algorithm: TREE (n)


for i := 1 to n do
declare new node
node.leftchild := least (list)
node.rightchild := least (list)
node.weight) := ((node.leftchild).weight) + ((node.rightchild).weight)
insert (list, node);
return least (list);

At the end of this algorithm, the weight of the root node represents the optimal cost.

Example 1

Let us consider the given files, f1, f2, f3, f4 and f5 with 20, 30, 10, 5 and 30 number of
elements respectively.

If merge operations are performed according to the provided sequence, then

M1 = merge f1 and f2 => 20 + 30 = 50

M2 = merge M1 and f3 => 50 + 10 = 60


M3 = merge M2 and f4 => 60 + 5 = 65

M4 = merge M3 and f5 => 65 + 30 = 95

Hence, the total number of operations is

50 + 60 + 65 + 95 = 270

Now, the question arises is there any better solution?

Sorting the numbers according to their size in an ascending order, we get the following
sequence −

f4, f3, f1, f2, f5

Hence, merge operations can be performed on this sequence

M1 = merge f4 and f3 => 5 + 10 = 15

M2 = merge M1 and f1 => 15 + 20 = 35

M3 = merge M2 and f2 => 35 + 30 = 65

M4 = merge M3 and f5 => 65 + 30 = 95

Therefore, the total number of operations is

15 + 35 + 65 + 95 = 210

Obviously, this is better than the previous one.

In this context, we are now going to solve the problem using this algorithm.

Initial Set

Step-1
Step-2

Step-3

Step-4

Hence, the solution takes 15 + 35 + 60 + 95 = 205 number of comparisons.

Example 2

Input: n = 6, size = {2, 3, 4, 5, 6, 7}


Output: 68
Explanation: Optimal way to combine these files
PROGRAM

// C++ program to implement

// Optimal File Merge Pattern

#include<bits/stdc++.h>

using namespace std;

// Function to find minimum computation

int minComputation(int size, int files[])

// Create a min heap

priority_queue<int, vector<int>,

greater<int>> pq;

for(int i = 0; i < size; i++)

{
// Add sizes to priorityQueue

pq.push(files[i]);

// Variable to count total Computation

int count = 0;

while(pq.size() > 1)

// pop two smallest size element

// from the min heap

int first_smallest = pq.top();

pq.pop();

int second_smallest = pq.top();

pq.pop();

int temp = first_smallest + second_smallest;

// Add the current computations

// with the previous one's

count += temp;

// Add new combined file size

// to priority queue or min heap

pq.push(temp);

return count;

int main()
{

// No of files

int n = 6;

// 6 files with their sizes

int files[] = { 2, 3, 4, 5, 6, 7 };

// Total no of computations

// do be done final answer

cout << "Minimum Computations = "

<< minComputation(n, files);

return 0;

Output:
Minimum Computations = 68

You might also like