Current location - Training Enrollment Network - Mathematics courses - Is the algorithm redundant?
Is the algorithm redundant?
Reference source: b(int m, int k) is from natural number 1, 2, ... When the first number of the combination is selected, the following number is the combination of k- 1 numbers among the remaining m- 1 numbers. This transforms the combination problem of finding k from the number of m into the combination problem of finding k- 1 from the number of m- 1. Let the function introduce the working array a[] to store the solved combination number, and the appointed function puts the first number of the determined combination of k numbers into a[k]. When solving a combination, output a combination in []. The first number can be m, m- 1, ... After the function puts the first number of the determined combination into the array, there are two possible choices. Because the remaining elements of the combination have not been removed, it will be determined recursively. Or the combination is output because all elements of the combination have been determined. See the function comb in the following program for details.

procedure

# include & ltstdio.h & gt

# Define MAXN 100

int a[MAXN];

Empty comb (integer m, integer k)

{ int i,j;

for(I = m; I>= k;; I-)

{ a[k]= I;

if(k & gt; 1)

Comb (i- 1, k-1);

other

{ for(j = a[0]; j & gt0; j -)

printf("%4d ",a[j]);

printf(" \ n ");

}

}

}

void main()

{ a[0]= 3;

Combs (5, 3);

}

3. Traceability method

Backtracking method, also known as heuristic method, first temporarily gives up the limitation on the size of the problem, and lists and tests the candidate solutions of the problem one by one in a certain order. When it is found that the current candidate solution cannot be a solution, the next candidate solution is selected; If the current candidate does not meet the scale requirements of the problem, but meets all other requirements, continue to expand the scale of the current candidate solution and continue to explore. If the current candidate solution meets all requirements including the scale of the problem, the candidate solution is the solution of the problem. In backtracking method, the process of giving up the current candidate solution and finding the next candidate solution is called backtracking. The process of expanding the scale of the current candidate solution to continue the test is called forward test.

Problem combination problem

Problem description: Find all combinations of R numbers from natural numbers 1, 2, …, n. ..

Find the solution of the problem by backtracking method, and store the found combinations in a[0], a[ 1], …, a[r- 1] in descending order. The elements of this combination satisfy the following attributes:

(1) a[i+ 1]>a, the latter number is greater than the previous number;

(2)a-I & lt; =n-r+ 1 .

According to the idea of backtracking, the process of solving can be described as:

Firstly, the condition that the number of combinations is r is discarded, and the candidate combinations only start from a number 1 Because the candidate solution satisfies all the conditions except the scale of the problem, the scale of the candidate solution satisfies the above conditions (1), and the candidate combination is changed to 1, 2. Continue this process and get the candidate combination 1, 2, 3. The candidate solution satisfies all conditions including the scale of the problem, so it is a solution. On the basis of this solution, the next candidate solution is selected. Because 3 on a[2] is adjusted to 4 and then to 5, all the requirements of the problem are met, and the solutions of 1, 2,4 and 1, 2,5 are obtained. Since 5 can no longer be adjusted, it is necessary to backtrack from a[2] to a[ 1]. At this time, a[ 1]=2, which can be adjusted to 3, and the solution of 1, 3,4 is obtained. Repeat the above exploration forward and backtracking until you want to backtrack from a[0], that is, you have found all the solutions to the problem. According to the above ideas, the program is as follows:

procedure

# Define MAXN 100

int a[MAXN];

Empty comb (integer m, integer r)

{ int i,j;

I = 0;

a = 1;

Do {

If (a-I <; =m-r+ 1

{ if (i==r- 1)

{ for(j = 0; j & ltr; j++)

printf("%4d ",a[j]);

printf(" \ n ");

}

a++;

Continue;

}

other

{ if (i==0)

Return;

a[-I]++;

}

} while ( 1)

}

Master ()

Combs (5, 3);

}

4. The law of greed

Greedy method is a method that does not pursue the optimal solution, but only hopes to get a satisfactory solution. Generally speaking, the greedy method can get a satisfactory solution quickly, because it saves a lot of time that must be spent on exhausting all possibilities in order to find the optimal solution. Greedy method is often based on the current situation to make the best choice, without considering all possible overall situation, so greedy method should not go back.

For example, in order to minimize the number of change coins in shopping, we don't consider various distribution schemes of change, but start with the currency with the largest face value and consider all currencies in descending order. Try to use the currency with the largest face value first, and then consider the next currency with a smaller face value when the amount is less than the currency with the largest face value. This is the use of greed. This method is always the best here because of the ingenious arrangement of the types and face values of coins issued by banks. If you only have coins with face values of 1, 5 and 1 1 unit, you want to find coins with a total amount of 15 unit. According to the greedy algorithm, we should find 1 coins with unit face value 1 and 4 coins with unit face value1,and * * * get back 5 coins. But the optimal solution should be three coins with a face value of 5 units.

Packaging problem

Description of the problem: The packing problem can be simply described as follows: there are n kinds of articles numbered 0, 1, …, n- 1, and their volumes are v0, v 1, …, vn- 1 respectively. Put these n kinds of articles in several boxes with V capacity. It is agreed that the volume of these N kinds of articles cannot exceed V, that is, for 0 ≤ I < N, there are 0 < VI ≤ V ... Different packaging schemes may require different numbers of boxes. The packing problem requires that the number of boxes containing these N kinds of articles should be less.

If we divide the set of n items into all subsets of n items or less, we can find the optimal solution. But the total number of all possible divisions is too large. For an appropriately large n, it takes an unbearable time to find out all possible divisions. Therefore, the packing problem adopts a very simple approximate algorithm, that is, greedy algorithm. This algorithm puts items in the first box that can be put in turn. Although the algorithm can not guarantee to find the optimal solution, it can still find a good solution. Without loss of generality, we assume that the volumes of n items are arranged in descending order, that is, there are v0 ≥ v1≥ … ≥ VN-1. If the above requirements are not met, just sort the n items by volume from large to small, and then renumber them according to the sorting results. The packing algorithm is briefly described as follows:

{Enter the volume of the box;

Enter the number of items n;

Enter the volume of each item in descending order;

The preset used container chain is empty;

The default used box counter box_count is 0;

for(I = 0; I & ltn;; i++)

{Starting from the first used box, look for the box J that can put the article I in order;

If (I can't put more items into the used box)

{Use another box and put the item I into it;

box _ count++;

}

other

Put the article I into the box j;

}

}

The above algorithm can find out the required number of boxes box_count and the content of each box. The following example shows that the algorithm may not find the optimal solution. There are six kinds of articles with volumes of 60, 45, 35, 20, 20 and 20 respectively, and the box volume is 100 units. According to the above algorithm, three boxes are needed, and the items in each box are: the first box contains items 1 and 3; The second box contains items 2, 4 and 5; The third box contains item 6. The optimal solution is two boxes containing 1, 4, 5 and 2, 3, 6 respectively.

If the contents of each box are represented by a linked list, the first node pointer of the linked list is stored in a structure that records the remaining space of the box contents and the first pointer of the linked list. In addition, the information of all boxes also constitutes a linked list. The following is a program written according to the above algorithm.

}

divide and rule

The calculation time of any problem that a computer can solve is related to its scale n. The smaller the scale of the problem, the easier it is to solve it directly, and the less the calculation time required for solving it. For example, for the sorting problem of n elements, when n= 1, there is no need to calculate; When n=2, only one comparison is needed to arrange the order; When n=3, only three comparisons are needed. When n is large, the problem is not so easy to deal with. Sometimes it is quite difficult to solve a large-scale problem directly.

The design idea of divide-and-conquer method is to divide a big problem that is difficult to solve directly into some small-scale problems, so as to divide and rule one by one.

If the original problem can be divided into k subproblems (1

The problems that can be solved by the divide-and-conquer method generally have the following characteristics:

The scale of (1) is reduced to a certain extent, and the problem is easy to solve;

(2) The problem can be decomposed into several smaller problems, that is, the problem has the optimal substructure property;

(3) The solution of the subproblem decomposed by this problem can be merged into the solution of this problem;

(4) The subproblems decomposed by this problem are independent of each other, that is, the subproblems do not contain common subproblems.

The first feature mentioned above is that it can satisfy most problems, because the computational complexity of the problem generally increases with the increase of the scale of the problem; The second feature is the premise of applying divide-and-conquer method, and most problems can be satisfied. This feature embodies the application of recursive thought. The third feature is the key. Whether the divide-and-conquer method can be used depends entirely on whether the problem has the third characteristic. If the first and second features are available, but the third feature is not, greedy method or dynamic programming method can be considered. The fourth characteristic is related to the efficiency of divide-and-conquer method. If the subproblem is not independent, then the divide-and-conquer method needs to do a lot of unnecessary work and solve the subproblem of the public repeatedly. At this time, although the method of divide and conquer can be used, the general dynamic programming method is better.

Divide and conquer has three steps at each recursive level:

(1) decomposition: the original problem is decomposed into several smaller, independent subproblems with the same form as the original problem;

(2) Solution: If the subproblem is small and easy to solve, directly solve it, otherwise recursively solve each subproblem;

(3) Merge: Merge the solutions of each sub-problem into the solution of the original problem.

6. Dynamic planning method

Complex problems often encountered cannot be simply decomposed into several sub-problems, but will be decomposed into a series of sub-problems. Simply using the method of decomposing a big problem into sub-problems and then synthesizing the solutions of the sub-problems to derive the solution of the big problem will increase the time-consuming of solving the problem by a power series according to the scale of the problem.

In order to save the time of finding the same subproblem repeatedly, an array is introduced, and the solutions of all subproblems are stored in the array whether they are useful for the final solution or not. This is the basic method used in dynamic programming. The following first illustrates the use of dynamic programming method with examples.

The problem is to find the longest common * * * character subsequence in two character sequences.

Problem description: A subsequence of a character sequence refers to a character sequence formed by randomly (not necessarily continuously) removing several characters (maybe none) from a given character sequence. Let the given character sequence X = "x0, x 1, …, xm- 1 ",and the sequence Y = "y0, y 1, …, yk- 1" is a subsequence of X, and there is a strictly increasing subscript sequence of X.

Considering how to decompose the longest common subsequence problem into subproblems, let a = "A0, a 1, …, am- 1", b = "B0, b 1, …, bm- 1", and z = "z0, z" is not difficult to prove.

(1) if am- 1=bn- 1, then ZK-1= am-1= bn-1,and "z0, z 1.

(2) If am- 1! =bn- 1, then if zk- 1! =am- 1, which means "z0, z 1, …, zk- 1" is "a0, a 1, …, am-2" and "b0, b 1, ….

(3) If am- 1! =bn- 1, then if zk- 1! =bn- 1, then the meanings of "z0, z 1, …, zk- 1" are "a0, a 1, …, am- 1" and "b0, b/kloc"

In this way, if am- 1=bn- 1, we can further solve a subproblem and find out "a0, a 1, …, am-2" and "b0, b 1, …, …" =bn- 1, to solve the two sub-problems, we should find the longest childe sequence of "a0, a 1, …, am-2" and "b0, b 1, …, bn- 1" and "a0, A668".

The code is as follows:

# include & ltstdio.h & gt

# include & ltstring.h & gt

# Definition number 100

char a[N],b[N],str[N];

int lcs_len(char *a,char *b,int c[ ][ N])

{ int m=strlen(a),n=strlen(b),I,j;

for(I = 0; I<= m;; i++)c[0]= 0;

for(I = 0; I < = n; i++)c[0]= 0;

for(I = 1; I<= m;; i++)

for(j = 1; j & lt= m; j++)

if (a[i- 1]==b[j- 1])

c[j]= c[I- 1][j- 1]+ 1;

else if(c[I- 1][j]& gt; =c[j- 1])

c[j]= c[I- 1][j];

other

c[j]= c[j- 1];

return c[m][n];

}

char *buile_lcs(char s[ ],char *a,char *b)

{ int k,i=strlen(a),j = strlen(b);

k=lcs_len(a,b,c);

s[k]=“”;

while(k & gt; 0)

if(c[j]= = c[I- 1][j])I-;

else if(c[j]= = c[j- 1])j-;

else { s[-k]= a[I- 1];

I-; j-;

}

Return to s;

}

void main()

{printf ("Enter two strings (<% d)! \n”,N);

scanf("%s%s ",a,b);

printf("LCS=%s\n ",build_lcs(str,a,b));

}