NOTE: Reprint please indicate: The basic idea of http://www.cnblogs.com/ECJTUACM-873284962/enumeration method
The basic idea of enumeration method is to enumerate all possible states according to the problem presented, and to test what is needed and what is not needed by the condition given by the problem. The proposition can be set up, that is, its solution.
Enumeration structure: Loop + judgment statement.
Conditions of the enumeration method
Although the enumeration method is essentially a search strategy, it differs from the backtracking method that is later spoken. The problem solved by the enumeration method must satisfy two conditions:
⑴ can predetermine the number of elements per state n;
The possible value of the ⑵ state element A1,a2,...,an is a continuous range.
The frame structure of enumeration method
Sets the minimum value of the ai1-state element AI, the maximum value of the aik-state element Ai (1≤i≤n), which is a11≤a1≤a1k,a21≤a2≤a2k, Ai1≤ai≤aik,......,an1≤an≤ank
For A1←A11 to a1k does for a2←a21 to a2k does .... .......... For AI←AI1 to AIK does ... ............ For An←an1 to Ank do if state (a
1
,..., a
I
,..., a
N
) satisfies the test condition then the solution of the output problem;
Advantages and disadvantages of enumeration method
Advantages of the enumeration method:
⑴ because the enumeration algorithm is generally the "literal translation" of real life problems, it is more intuitive and easy to understand .
⑵ because the enumeration algorithm is based on the investigation of a large number of States, even the exhaustive state, so the correctness of the algorithm is easier to prove
Disadvantages of the enumeration method:
The efficiency of an enumeration algorithm depends on the number of enumeration states and the cost of a single State enumeration, so it is less efficient.
Enumeration: Enumerates objects, scopes, and constraints directly based on test instructions.
Pay attention to serious examining, do not neglect any conditions
Example
Example 1: Weight weighing
"Problem description" with 1g, 2g, 3g, 5g, 10g, 20g weight of each of several (its total weight <=1000), to use these weights can be weighed different weight number.
"File input" input 1g, 2g, 3g, 5g, 10g, 20g, the number of weights.
The "file output" output can weigh the number of different weights.
"Sample Input" 1 1 0 0 0 0
"Sample Output" 3
"Analysis" according to the input weights information, the maximum number of each weight available is determined, and each weight number is continuous, can take 0 to the maximum number, so conform to the enumeration method of two conditions, you can use the enumeration method. When enumerating, the weight can be composed of any one or more of the 1g,2g,......, 20g weights, the enumeration object can be determined as a weight of 6 weights, the range is the number of each weight. When deciding, it is only necessary to judge whether the weight gained is new, or the previous one has been awarded. Because of the weight <=1000g, you can open an array of a[1001] to weigh.
The C + + code is as follows:
#include <iostream>using namespace Std;int a[1001]={0};int main () { int a,b,c,d,e,f,i,sum,num; int arr[7]; int w[7]={0,1,2,3,5,10,20}; cin>>a>>b>>c>>d>>e>>f; For (arr[1]=0, arr[1]<=a; arr[1]++) for (arr[2]=0; arr[2]<=b; arr[2]++) for (arr[3]=0; arr[3]<=c; arr[ 3]++) for ( arr[4]=0, arr[4]<=d; arr[4]++) for ( arr[5]=0; arr[5]<=e; arr[5]++) for (arr[6]=0; arr[6) <=f; arr[6]++) { sum=0; for (I=1; i<=6; i++) { sum+=arr[i]*w[i]; a[sum]=1; } } num=0; for (I=1; i<=1000; i++) { if (a[i]==1) num++; } Cout<<num<<endl;return 0;}
Example 2: Match stick equation
"Problem description" give you n a match stick, you can spell out how many shape like "a+b=c" equation? A, B, and C in the equation are integers that are spelled with a match stick (if the number is nonzero, the highest bit cannot be 0). Spell the number 0-9 with a match stick:
Attention:
1. The plus sign and the equals sign each need two sticks
2. If a≠b, A+b=c and b+a=c are considered different equations (A, B, c≥0)
3. N sticks must all be used
Input Enter an integer n (n≤24).
The number of different equations that the output output can spell.
Problem Brief: Give you n (n<=24) A match stick, ask you to spell out "A + B = C" Such an equation, the number of solutions.
Idea: The subject up to 24 matches, equal sign and the plus sign share 4 matches, so a,b,c these 3 numbers need 20 matches. We examine the maximum value of a and B May: 0~9 The 10 number of matches used by 6,2,5,5,4,5,6,3,7,6, it is obvious that the number 1 with a match stick for at least 2, may let B for 1, then A and C can use up to 18 matches, and C>=a, The maximum value of a that satisfies a condition is 1111. So the range of enumerations A and B is from 0~1111.
To speed up, the number of match sticks required for all integers from 0 to 2222 is calculated in advance to be saved in the array.
The code is as follows:
#include <iostream>using namespace std;int a[2223]={6,2,5,5,4,5,6,3,7,6};const int b[10]={6,2,5,5,4,5,6,3,7,6 };//calculates the number of matches required by the natural number n int need (int n) { int tmp, NUM; num=0; if (n==0) return 6; while (n>0) { tmp=n%10; NUM+=B[TMP]; n/=10; } return num;} int main () { int n,a,b,c,d,sum; cin>>n; sum=0; for (int i=10; i<2223; i++)//preprocessing a[i]=need (i); for (int i=0, i<=1000; i++) {for (int j=0; j<=1000; J + +) { a=a[i]; B=A[J]; C=n-4-a-b; D=A[I+J]; if (d==c) sum++; } } cout<<sum<<endl; System ("PAUSE"); return 0;}
Optimization of enumeration algorithm
Time complexity of the enumeration algorithm: Total number of States * time spent in a single state.
⑴ extract effective information;
⑵ reduction of repetitive calculations;
⑶ the original problem into a smaller problem;
⑷ according to the nature of the problem;
⑸ introduction of other algorithms
Example
"Example 3" gives you an n (n<=105) integer, and then you have M (m<=105) to ask. Each inquired two integers I and J, which asked the I-number to the sum of the first J-numbers all numbers.
Naive algorithm:
#include <iostream>using namespace Std;int main () { int sum,n,m,x,y,i,j,a[106]; cin>>n>>m; for (I=1; i<=n; i++) cin>>a[i]; for (I=1; i<=m; i++) { cin>>x>>y; sum=0; for (j=x; j<=y; j + +) sum+=a[j]; cout<<sum<<endl; } return 0;}
Optimization algorithm:
Calculate S[i]=s[i-1]+a[i First]
cin>>n; for (i=1;i<=n;i++) {cin>>a[i];s[i]=s[i-1]+a[i],} for (i=1;i<=m;i++) { cin>>x>>y; cout<<s[y]-s[x-1]<<endl; }
"Example 4" Maximum sub-matrix problem
"Problem description" given a two-dimensional array (with positive or negative numbers), find and maximize the sub-matrices from it. For example:
Method 1: "Literal translation" enumeration procedure
for (x1=1;x1<=n;x1++)//enumeration rectangle upper left corner (x1,y1) for (y1=1;y1<=n;y1++) for ( x2=1; x2<=n; x2++)//enumeration rectangle the lower right corner (X2,y2) for (y2=1;y2<=n;y2++) The sum of the elements in the upper-left corner (x1,y1) of the lower- right corner of the rectangle (x2,y2);
Set map as the number matrix, sum as the sums of elements within the current rectangle, best is the optimal solution. The investigation process is as follows:
Sum=0;for (x=x1;x<=x2;x++)//calculates the and for (y=y1;y<=y2;y++) Sum=sum+map[x][y of elements within the current rectangle ; if (sum>best) Best =sum;//adjusting the optimal solution
This algorithm is fairly coarse, and the cost of enumeration state is O (N6)
Method 2: Start by reducing the repetition calculation
There is a one-dimensional situation can be generalized to two-dimensional, in the upper left corner of the (x1,y1) in the lower right corner (x2,y2) is the sum of the elements of the rectangle, we can also initialize first, the upper-left corner is (x, y) is the lower right corner of the element of the rectangle (S[x][y]).
for (x1=1;x1<=n;x1++)//enumeration Rectangle upper-left corner (x1,y1) {for (y1=1;y1<=n;y1++) { cin>>map[i][j]; S[I][J]=S[I-1][J]+S[I][J-1]-S[I-1][J-1]+MAP[I][J];} }
For the sum of the elements of the rectangle in the upper-left corner (X1,Y1) of the State (X2,Y2), you can instead:
Sum=s[x2][y2]-s[x1-1][y2]-s[x2][y1-1]+s[x1-1][y1-1];if (sum>best) best=sum;//adjustment Optimal Solution
The time complexity of the whole algorithm is reduced to O (N4) due to the calculated results.
Method 3: Extract the appropriate information
It is easy to observe that the maximal sub-matrix problem is the promotion of maximal continuous sub-sequences and problems, and the one-dimensional problem is promoted to a two-dimensional problem by replacing a line with a polygon. So our method of calculating the maximum sub-matrix is to accumulate the number of rows in a row to obtain the maximum value.
But there is one more problem, that is, how to efficiently store the matrix?
We can think of: in a one-dimensional series, set array B[i] to represent from the 1th element to the first element of the and, if you want to request the first element to the J element of the and, only need to calculate the value of b[j]-b[i-1] is OK. This is generalized to a two-dimensional matrix, set B[i][j] that represents the first element of the Matrix J and A[i][j] represents the element data, then compressed storage:
for (i=1;i<=n;i++) for (j=1;j<=n;j++) {cin>>a[i][j];b[i][j]=b[i-1][j]+a[i][j];}
Therefore, we can use the triple loop to find all the rectangle values, that is, the enumeration start line I and the terminating row J, the compressed sub-rectangle becomes a row, becomes one dimension to seek the maximum field and the problem.
namely T[k]=max (t[k-1],0) +b[j][k]-b[i-1][k];
Time Complexity of O (N3)
Core code:
Sum=-0x7fffffff;for (i=1;i<=n;i++) //stage: Start line {for (j=i;j<=n;j++) //Status: End line { t[1]=b[j][1 ]-B[I-1][1]; Initializes the value for the 1th column for (k=2;k<=n;k++) //Decision: The first few columns { T[k]=max (t[k-1],0) +b[j][k]-b[i-1][k]; if (t[k]>sum) sum=t[k];}} } cout<<sum<<endl;
Algorithm--enumeration policy