Optimization
Introduction
DFS (Depth-First Search) is a common algorithm that can solve most problems, but in most cases, it is a "cheating" algorithm—rarely is brute-force search the intended solution. This is because DFS has a particularly high time complexity. (If you haven't learned DFS, please study it first.)
Since it cannot be the intended solution, let's try to cheat more points. This article will introduce some practical optimization techniques (commonly known as "pruning").
First, here is a DFS template. Subsequent templates will be modified based on this.
1 2 3 4 5 6 7 8 9 10 11 | |
Here, ans can be a record of the solution, so "choose the best between current solution and existing solution" becomes outputting the solution.
Pruning Methods
The most commonly used pruning techniques are three: memoization search, optimality pruning, and feasibility pruning.
Memoization Search
In search, the same input values often yield the same solution. Thus, we can use an array to memoize results. For details, see Memoization Search.
Template:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | |
Optimality Pruning
Another reason for slow search is continuing to search when the current solution is already worse than the existing solution. We only need to check whether the current solution is worse than the existing one.
Template:
1 2 3 4 5 6 7 8 9 10 11 12 | |
Feasibility Pruning
During search, continuing to explore when the current solution is already infeasible is another cause of slowness.
Template:
1 2 3 4 5 6 7 8 9 10 11 12 | |
Pruning Ideas
There are many pruning ideas, most of which require analysis based on specific problems. Here are a few common ones:
-
Extreme Case Method: Consider extreme cases. If even the most extreme (ideal) case cannot satisfy the conditions, then the actual search results certainly won't be better.
-
Adjustment Method: By comparing subtrees, prune duplicate subtrees and those that are clearly not the most "promising."
-
Mathematical Methods: For example, using connected components in graph theory, modular equations in number theory, inequality scaling to estimate lower bounds, etc.
Example
Job Assignment Problem
There are \(n\) (\(1 \leq n \leq 15\)) jobs to be assigned to \(n\) people, each person completing one job. The time for the \(i\)-th person to complete the \(k\)-th job is a positive integer \(t_{i,k}\) (\(1 \leq t_{i,k} \leq 10^4\)), where \(1 \leq i, k \leq n\). Determine an assignment scheme that minimizes the total time to complete all \(n\) jobs.
Since each person must be assigned a job, we can create a 2D array time[i][j] to represent the time for person \(i\) to complete job \(j\). Use a loop to assign jobs starting from the first person until everyone is assigned. When assigning a job to the \(i\)-th person, loop through each job to check if it has already been assigned. If not, assign it to person \(i\); otherwise, check the next job. Use a 1D array is_working[j] to indicate whether job \(j\) has been assigned: is_working[j]=0 if unassigned, otherwise is_working[j]=1. Using backtracking, after the worker loop ends, return to the previous worker, cancel the assigned job, and assign the next job until a feasible assignment is found. This way, backtracking to the first worker yields all feasible solutions.
Checking job assignments essentially means ensuring that the first dimension subscripts of the 2D array are all different and the second dimension subscripts are all different for a feasible solution. Since we want the minimum total time to complete all \(n\) jobs, i.e., the smallest total time among feasible solutions, define a global variable cost_time_total_min to represent the minimum total time found so far. Initialize cost_time_total_min as the sum of time[i][i], i.e., the sum of diagonal elements. After all people are assigned jobs, compare count with cost_time_total_min. If count is less than cost_time_total_min, an optimal solution is found, and assign count to cost_time_total_min.
Considering algorithm efficiency, a pruning optimization can be applied. When computing the local cost variable count, if count is already greater than cost_time_total_min, there is no need to continue assigning further, because the resulting solution will certainly not be optimal.
Reference Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | |
本页面最近更新:,更新历史
发现错误?想一起完善? 在 GitHub 上编辑此页!
本页面贡献者:OI-wiki
本页面的全部内容在 CC BY-SA 4.0 和 SATA 协议之条款下提供,附加条款亦可能应用