This article is reproduced, the original address: http://www.cppblog.com/3522021224/archive/2007/06/16/26429.aspx
I. Basic concepts of greedy Algorithms
When a problem has the optimal sub-Structural quality, we will think of using dynamic programming to solve it. But sometimes there are simpler and more effective algorithms. Let's look at an example of coin search. Assume there are four types of coins with a nominal value of five cents, one cent, five cents and one cent. Now I am looking for a customer with three cents. At this time, we will give two coins, one cent, and three cent coins to the customer without thinking about them. Compared with other methods, this method has the lowest number of coins. Here, we subconsciously use this coin search algorithm: First, we select a maximum coin with a nominal value not greater than three points, that is, two points and five points; then we subtract two points and five points from the three points, the remaining triangle points are eight points, and the biggest coin with a nominal value not greater than eight points, that is, the second and fifth points, remains unchanged. This method for finding coins is actually a greedy algorithm. As the name suggests, greedy algorithms always make the best choice for the moment. That is to say, the greedy algorithm does not take the overall optimization into consideration. All it makes is a local optimal choice in a certain sense. Of course, we hope that the final result of the greedy algorithm will be the optimal as a whole. The result of the coin search algorithm described above is an overall optimal solution. Finding a coin is essentially an optimal sub-structure. It can be solved using a dynamic programming algorithm. However, we can see that greedy algorithms are simpler, more direct, and more efficient in solving problems. This utilizes some features of the problem itself. For example, the preceding coin search algorithm utilizes the particularity of the coin's face value. If the nominal value of a coin is changed to one cent, five cents, and one cent, a cent is worth five cents. We also use the greedy algorithm to find one cent coin and four cent coin for the customer. However, a coin of three or five points is obviously the best way to find it. Although the greedy algorithm does not obtain the overall optimal solution for all problems, it can produce the overall optimal solution for many problems with a wide range. Single-source shortest path and Minimum Spanning Tree. In some cases, even if the greedy algorithm cannot obtain the overall optimal solution, the final result is a good Approximate Solution of the optimal solution.
Ii. Algorithm for Solving activity arrangement problems
The issue of activity arrangement is a good example that can be effectively solved using greedy algorithms. This issue requires efficient scheduling of a series of activities to compete for a certain public resource. Greedy algorithms provide a simple and beautiful way to allow as many activities as possible to use public resources.
Set of N activities e = {1, 2 ,..., N}. Each activity requires the use of the same resource, such as the speech venue. Only one activity can use this resource within the same time period. Each activity I has a start time si that requires the use of the resource and an end time Fi, and Si <fi. If activity I is selected, it occupies resources within the half-open time range [Si, FI. If the interval [Si, FI] and interval [SJ, FJ] do not overlap, it is said that activity I is compatible with activity J. That is to say, when Si ≥ fi or SJ ≥ FJ, activity I is compatible with activity J. The most compatible sub-set is selected in the given activity set.
In the greedy algorithm gpeedyselector given below to solve the problem of activity arrangement, the start time and end time of each activity are stored in arrays S and f {, and are not in descending order of the End Time :. f1 ≤ F2 ≤... ≤ Fn. If the given activity is not arranged in this order, we can use the O (nlogn) Time to rearrange it.
template< class type>void greedyselector(int n, type s[ 1, type f[ ], bool a[ ] ] { a[ 1 ] = true; int j = 1; for (int i=2;i< =n;i+ + ) { if (s[i]>=f[j]) { a[i] = true; j=i; } else a[i]= false; }}
GreedyselectorUse set a to store selected activities. Activity I is in set a, and only if the value of a [I] is true. Variable J is used to record the last activity added to. Because the input activities are arranged in a non-descending order of the end time, FJ is always the maximum end time of all activities in the current set a, that is:
Greedy Algorithm greedyselector selects Activity 1 from the beginning and initializes J to 1. Check whether activity I is compatible with all selected activities. If it is compatible, add the activity I to the selected activity set a. Otherwise, do not select activity I, and continue to check the compatibility of the next activity with the activity in set. Because Fi is always the maximum end time of all activities in current set, therefore, the full and necessary condition that activity I is compatible with all activities in current set a is that its start time s is not earlier than the end time FJ, Si ≥ Fj of the activity J recently added to set. If activity I is compatible with it, I becomes the activity in the recently joined group A, thus replacing the position of activity J. Because the input activities are arranged in a non-descending order of the completion time, the greedyselector algorithm always selects compatible activities with the earliest completion time to join in set. Intuitively, selecting a compatible activity in this way leaves as much time as possible for unscheduled activities. That is to say, the greedy choice of this algorithm is to maximize the remaining configurable time periods so as to arrange as many compatible activities as possible. The greedyselector algorithm is highly efficient. When the input activities are arranged in a non-descending order of the end time, the algorithm only needs to schedule n activities in G (n) time so that the most activities can use public resources in a compatible manner.
For example, set the start time and end time of the 11 activities to be arranged in a non-descending order of the end time as follows:
I |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
S [I] |
1 |
3 |
0 |
5 |
3 |
5 |
6 |
8 |
8 |
2 |
12 |
F [I] |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
The calculation process of the greedyselector algorithm.
Each row in the figure corresponds to an iteration of the algorithm. The Shadow bar indicates the activity in the selected set a, while the blank bar indicates that the activity is currently checking its compatibility. If the start time Si of the checked activity I is less than the end time Fj of the recently selected activity, activity I is not selected; otherwise, activity I is added to set.
Iii. Algorithm Analysis
Greedy algorithms cannot always obtain the overall optimal solution of the problem. But for the problem of activity arrangement, greedy algorithm greedyse-1ector can always obtain the overall optimal solution, that is, it finally determined the maximum size of compatible activity set. We can use mathematical induction to prove this conclusion.
In fact, set E = {1, 2 ,..., N} is the set of given activities. Because the activities in E are arranged in a non-descending order of the end time, Activity 1 has the earliest completion time. First, we need to prove that the problem of activity arrangement has an optimal solution starting with greedy selection, that is, the optimal solution contains Activity 1. It is an optimal solution for the given activity arrangement problem, and activities in a are arranged in non-descending order according to the end time. The first activity in a is activity K. If k = 1, A is an optimal solution starting with greedy choice. If K> 1, we set B = A-{k} U {1 }. Because F1 ≤ fk and activities in a are mutually compatible, activities in B are also mutually compatible. Because the number of activities in B is the same as that in a, and a is the best, B is also the best. That is to say, B is an optimal activity arrangement that begins with activity 1 with greed. Therefore, we prove that there is always an optimal activity arrangement scheme starting with greedy choices.
Furthermore, after the greedy choice is selected, the original problem is simplified to the sub-Problem of arranging activities for all activities compatible with activity 1 in E. That is, if A is an optimal solution of the original problem, then a' = A-{I} is an optimal solution of the activity arrangement problem. In fact, if we can find a solution B 'for E, which contains more activities than A', then adding activity 1 to B' will generate a solution B for E, it contains more activities than. This is in conflict with the adequacy of. Therefore, the greedy choice made in each step simplifies the problem into a smaller subproblem that has the same form as the original problem. The greedy algorithm greedyselector generates an optimal solution for the original problem.
4. Basic Elements of greedy Algorithms
The greedy algorithm solves a problem through a series of choices. Every choice it makes is the best choice in a certain sense in the current state, that is, greedy choice. It is expected that the final result will be the optimal solution of the problem through the greedy choice made each time.This heuristic strategy does not always work, but in many cases it can indeed achieve the expected purpose. The greedy algorithm for solving the problem of activity arrangement is an example. Next we will focus on the general features of the problems that can be solved using greedy algorithms.
For a specific question, how do we know whether greedy algorithms can be used to solve this problem and whether we can obtain an optimal solution? It is difficult to give a positive answer to this question. However, from many problems that can be solved using greedy Algorithms
We can see that they generally have two important properties:Greedy choiceAndOptimal sub-structure.
1.Greedy choice
The so-called greedy choice is that the overall optimal solution of the problem can be achieved through a series of local optimal choices, that is, greedy choice.. This is the first basic element for the feasibility of greedy algorithms and the main difference between greedy algorithms and Dynamic Planning Algorithms. In the dynamic planning algorithm, the choice made in each step is often dependent on the solution of related subproblems. Therefore, you can make a choice only after solving the problem.In the greedy algorithm, the best choice is made only in the current state, that is, the local optimal choice.Then we can solve the corresponding sub-problems generated after this selection. Greedy choices made by greedy algorithms can depend on previous choices, but they do not depend on future choices or on subproblems. Due to this difference, the dynamic planning algorithm usually solves the sub-Problems in the bottom-up mode, while the greedy algorithm is usually carried out in the top-down mode, make greedy choices in an iterative manner. Every greedy choice is to simplify the problem to a smaller subproblem.
For a specific problem, to determine whether it is greedy, we must prove that the greedy choice made by each step ultimately leads to an overall optimal solution of the problem.We can usually use the method we use to prove the greedy and selective nature of activities.First, we examine the overall optimal solution of the problem, and prove that the optimal solution can be modified, so that it can begin with greedy choice. After greedy selection, the original problem is simplified to a smaller subproblem.Then, it is proved by mathematical induction that, by making greedy choices at each step, an overall optimal solution of the problem can be obtained. It is proved that the key to simplifying the problem after greedy selection into a similar subproblem of smaller scale is to use the optimal substructure of the problem.
2.Optimal sub-structure
When the optimal solution of a problem includes the optimal solution of its subproblems, it is called the problem has the optimal substructure. The nature of the problem is a key feature of the problem that can be solved using a dynamic planning algorithm or greedy algorithm. In the issue of activity arrangement, the optimal sub-structure is as follows: if A is an optimal solution for positive activity arrangement that contains Activity 1, then, the compatible activity set a' = A-{1} is an optimal solution for the activity arrangement problem of E' = {I, e: Si ≥ F1.
3.Difference between greedy algorithms and Dynamic Planning Algorithms
Both greedy algorithms and dynamic planning algorithms require the optimal sub-structure of the problem, which is one of the two types of algorithms. However, a greedy algorithm or dynamic planning algorithm should be used to solve a problem with the optimal sub-structure? Can we use greedy algorithms to solve problems that can be solved using dynamic planning algorithms? Next we will study the two classic Optimization Problems and illustrate the main differences between greedy algorithms and dynamic planning algorithms.
V. 0-backpack Problems
N items and a backpack are given. The Weight of item I is W, the value is V, and the size of the backpack is C. How should I select the items in the backpack to maximize the total value of the items in the backpack? When you choose to attach a backpack to an item, you only have two options for each item I: attach a backpack or not attach a backpack. You cannot attach item I to a backpack multiple times or just part of item I.
The formal description of this problem is that given C> 0, wi> 0, VI> ≤ I ≤ n, a 0-1 direction of N yuan is required.
Quantity (XL, X2 ,..., XN), so that ≤ C and maximum.
Backpack problem: similar to the 0-1 backpack problem, the difference is that when you choose item I to load the backpack, you can choose part of item I, instead of all to load the backpack.
The formal description of this problem is that given C> 0, wi> 0, VI> ≤ I ≤ n, a n-element vector is required.
(X1, x2,... XN), 0 ≤ Xi ≤ 1, 1 ≤ I ≤ n makes ≤ C, and reaches the maximum.
These two types of problems have the optimal sub-structure nature. For a 0-1 backpack, if A is a set of items with the greatest value that can be loaded into a backpack with the capacity of C, AJ = A-{J} is n-1 Items 1, 2 ,..., J-1, J + 1 ,..., N a set of items with maximum value that can be loaded into a C-wi backpack. For a backpack, similarly, if an optimal solution contains item J, the weight wi of the item j is taken out from the optimal solution, the remaining items will be n-1 original item 1, 2 ,..., J-1, J + 1 ,..., N and items with the weight of WJ-wi can be loaded with C-W backpacks with the maximum value.
Although these two problems are extremely similar, the knapsack problem can be solved using greedy algorithms, while the 0-1 knapsack problem cannot be solved using greedy algorithms. The basic step for solving the knapsack problem using greedy algorithms is to calculate the unit weight value of each item first.
VJ/wi then, according to greedy selection strategy, put as many items with the highest weight value as possible into the backpack. If the total weight of all the items in the backpack does not exceed C, select items with a low unit weight value and load as many items as possible into the backpack. Follow this rule until the backpack is full. The specific algorithm can be described as follows:
void knapsack(int n, float m, float v[ ], float w[ ], float x[ ] ) sort(n,v,w); int i; for(i= 1;i<= n;i++) x[i] = o; float c = m; for (i = 1;i < = n;i ++) { if (w[i] > c) break; x[i] = 1; c-= w[i]; } if (i < = n) x[i] = c/w[i];}
The main computing time of the algorithm knapsack is to sort various items by their unit of weight value from large to small. Therefore, the upper bound of the algorithm's computing time is O (nlogn ). Of course, in order to prove the correctness of the algorithm, we must also prove that the problem of backpack is greedy.
This greedy Choice Policy does not apply to the 0-1 backpack problem. See the example in figure 2 (a). The size of the backpack is 50 kg; the weight of the item 1 is 10 kg; the value is 60 yuan; the weight of the item 2 is 20 kg, and the value is 100 yuan; the weight of the item 3 is 30 kg; the value is 120 RMB. Therefore, item 1 is worth 6 RMB per kilogram, item 2 is worth 5 RMB per kilogram, and item 3 is worth 4 RMB per kilogram. If you choose to use the greedy policy, you should first attach item 1 to the backpack. However, as shown in Figure 4-2 (B, the best choice is to choose item 2 and item 3 to load the backpack. Neither of the two solutions of Item 1 is optimal. If you are greedy for a backpack, you can get the optimal solution. solution 2 (c) shows the optimal solution.
For a 0-1 backpack, the greedy choice cannot obtain the optimal solution because it cannot guarantee that the backpack will eventually be filled up. The idle space of some backpacks reduces the value of each kilogram of space. In fact, when considering the choice of items with a 0-1 backpack problem, we should compare the final result caused by selecting this item and not selecting this item, and then make the best choice. As a result, many overlapping problems are exported. This is another important feature that can be solved using a dynamic planning algorithm. The dynamic planning algorithm can effectively solve the 0-1 knapsack problem.