A: Introduction
(1) believe that people who have done ACM are very familiar with the depth-first search of graphs and trees; The brute force method in the algorithm-is violent search (without any pruning of the search);
(2) Brute force search needs to be optimized, is the need to constantly pruning, early reduction of unnecessary search path, early detection of the filter conditions;
(3) The core problem of pruning is to design pruning judgment method, which search paths should be discarded, which search paths cannot be discarded (reserved);
(4) Effective pruning and filtering conditions need to consider the problem from the local and global, and discover the inherent law.
(5) Detailed pruning algorithm, see pruning algorithm (algorithm optimization)
Two: Sample validation
(1) title from POJ 1011 Sticks DFS + pruning
Title: Give some of the length of not more than 50 sticks, ask you to put these small sticks, the length of the same stick, of course, the smaller the better.
(2) Thinking of solving problems
1. First sum must be divisible by L.
2. L must be greater than or equal to the length Max of the longest stick given by the topic. From the above two points, it is thought that we can enumerate the L incrementally from Max until I successfully spell a stick with a sum/l length of L.
pruning techniques for searching for species:
3. Sort the input input from large to small, because a full stick of length K is always better than a few short sticks. Image some: If I want to spell 2 sticks with a length of 8, the first stick I spell 5 + 3 then spell the second stick but failed, and I have a long 2 and 1 sticks, I can use 5 + 2 + 1 to spell the first, and then try to spell the second
Branch, think carefully, you will find that this does not make sense, doomed to failure. We should leave 2+1 because 2+1 is more flexible than 3.
4.sticks of the same length do not search multiple times, for example: I have some sticks in my hand, of which there are 2 sticks with a length of 4, the current search status is 5+4+ .... (that is, three pieces of 5,4,2 length are put together,
... Deep search is not successful, so I do not need to use another 4 in the 5+4+ ...(adjacent to the topic before and after comparison)
5.when we start searching for a stick that's long as L, we always start with the longest unused stick currently in use., if the search is not successful, then it is shorter than the beginning, then must not achieve global success. Because every topic gives a stick to be used. If, there is
4
5 4 4 3 2 If you want to build a stick that grows to 6, then starting from 5, but obviously not 51, then I don't have to try to start with 6, because eventually 4 will be abandoned. In spelling 2nd 3 ... Sticks, the same.(smaller and more flexible)
6. The simplest of the last is,
&NB Sp for (int i = 0; i < n; i++)
for (int j = 0; J < N; j + +
{}
with
&NBSP ; for (int i = 0; i < n; i++)
for (int j = i+1; J < N; j + +)
&N Bsp The difference between {}
/ is not much to say.
7. Another pruning that I used, but the data effect on POJ is generally, with an array, sum[i] after saving the first stick, that is, the length of the sticks that are shorter or equal to the first sticks. Imagine, if all the sticks that remain together cannot be combined with my current state to spell a stick (from length) that is long as L , is it necessary to search?
(3) Detailed code
#include <iostream> #include <algorithm> #include <cstdio> #include <cstring>using namespace std;const int Max = 65;int N, len, Stick[max];bool flag, Vis[max];bool cmp (int a, int b) {return a > B;} void Dfs (int dep, int now_len, int u) {//DEP is the number of bars currently used, U is the bar currently being processed. if (flag) return;//the completed recursive return condition if (Now_len = = 0) {//Current length is 0, look for the next current longest bar. int k = 0; while (Vis[k]) K + +; Look for the first current longest little stick. Vis[k] = true; DFS (DEP + 1, stick[k], K + 1); Vis[k] = false; Return } if (Now_len = = len) {//The current length is Len, which is then pieced together into a stick. if (dep = = N) flag = true; Finished sign: All the n sticks have been spelled out. else Dfs (DEP, 0, 0); return;//recursive return condition} for (int i = u; i < n; i + +) if (!vis[i] && Now_len + stick[i] <= len)//filter conditions {if (!vis[i-1] && stick[i] = = Stick[i-1]) continue; Do not repeat the search: the most important pruning. Vis[i] = true; DFS (dEP + 1, Now_len + stick[i], i + 1); Vis[i] = false; }}int Main () {while (scanf ("%d", &n) && n! = 0) {int sum = 0; Flag = false; for (int i = 0; i < n; i + +) {scanf ("%d", &stick[i]); Sum + = Stick[i]; } sort (stick, stick + N, CMP); Sort from large to small. for (len = stick[0], len < sum, Len + +) if (sum% len = = 0)//Here is also equivalent to pruning (filter condition) {//enumeration can be The length of the sum evenly divisible. memset (Vis, 0, sizeof (VIS)); DFS (0, 0, 0); if (flag) break; } printf ("%d\n", Len); } return 0;}
(4) Comparison comparison POJ 1011 (this blog) and POJ 3900 (Pruning Algorithm (algorithm optimization))
DFS + Pruning Policy