When I went to school, I had a problem that had plagued me all the time. The problem was described as follows:
The cook puts all his dishes on one shelf. After work ends every day, he will arrange the dishes in ascending order. The problem is that the shelf is not stable. If one or more dishes are taken out at a time, the shelf may be dumped, so he has to flip the plate from one side. Because he only has two hands, he can only flip the plate with two hands. The problem is how to sort a messy sequence of dishes with a minimum flip count.
At that time, the problem was solved by means of exhaustion. However, many documents have shown that such optimal solutions can still be solved by dynamic programming. However, I have not found a way to break down the optimal subproblem, so I had to give up. Some time ago, I read the beauty of programming, and the pile of pancakes mentioned in the chapter "a pile of pancakes" are actually the same as the chef's dish placement, this article mentions the use of dynamic programming, but does not provide a solution. This reminds me of my thoughts. I turned out "Introduction to algorithms" and used Google, Baidu, and Yahoo, however, the solution using dynamic programming is still not found, but some discussions about this issue cannot be solved using dynamic programming. Although I did not find the answer, I turned out the old Code and saw the code that solved the "assembly line (Workstation) problem, at that time, the dynamic planning method and the exhaustive method were used to solve this problem. Now let's take a look at the code and the description of the "assembly line (Workstation) Problem:
The colonel automobile company produces cars in factories with two assembly lines. After a chassis enters each assembly line, different components are installed on the chassis of each Assembly station, the finished car leaves the end of the assembly line. 1. As shown in:
Figure 1. Assembly Line
There are n assembly stations on each assembly line, numbered j = 1, 2 ,..., n. Represent the J assembly station of assembly line I (I is 1 or 2) As S (I, j ). The J stations S (1, J) of assembly line 1 and J stations S (2, j) of Assembly Line 2 perform the same functions. However, these assembly stations are built at different times and adopt different technologies. Therefore, the time required for completing the Assembly on each station is different, this is true even for the assembly stations in the same position on the two assembly lines. The assembly time required for each assembly station is recorded as a (I, j), and the time required for the chassis to enter assembly line I is E (I ), the time required to exit assembly line I is X (I ). Under normal circumstances, the time taken to move the chassis from the previous station of an assembly line to the next station can be ignored, but occasionally, the unfinished chassis will be moved from one station in one assembly line to the next stop in another assembly line, for example, in case of an emergency order. Assume that the time taken to remove the assembly line I from the chassis of the assembly station S (I, j) is T (I, j ), the problem now is to determine which stations are selected in assembly line 1 and which stations are selected in assembly line 2 to minimize the total time for vehicles to pass through the factory. as shown in, the fastest time is to select 1, 3, and 6 assembly stations of assembly line 1 and 2, 2, and 5 assembly stations of Assembly Line 2.
Figure 2. One of the fastest route lines in the assembly line
According to the discussion in the introduction to algorithms, I first gave an algorithm using dynamic programming. The first step of dynamic planning is to describe the structural features of the optimal solution, that is, to define what is the optimal solution first. For assembly line problems, the optimal solution through S (I, j) is through the optimal solution of the previous station of S (I, j) plus the shortest time through S (I, j) station. For a colornel automobile company with two assembly lines, the fastest route through the assembly station S (1, J) can only be one of the following:
1. Through the assembly station S (1, J-1) the fastest route, then directly through the assembly line s (1, J );
2. The fastest route through the assembly station S (2, J-1), then move from assembly line 2 to assembly line 1, then through the assembly line s (1, J );
Likewise, the fastest route for the assembly station S (2, j) is symmetric. It can be seen that for S (1, J) station sub-problem is through S (1, J-1) and S (2, J-1) the fastest route, after establishing the optimal structure, the second step of dynamic planning can be executed, and the optimal solution of a problem is defined recursively using the optimal solution of the sub-problem. According to the previous analysis, it is easy to obtain the optimal recursive formula for the J-station:
The rest is about the implementation of the write algorithm. The following describes the Dynamic Programming Algorithm. First, we define a data structure, which is defined to facilitate the storage of intermediate data and reduce function parameters, it is not part of the dynamic planning method:
# Define max_line_station 20
Typedef struct tagfixlinepara
{
Int A [2] [max_line_station];
Int T [2] [max_line_station];
Int e [2];
Int X [2];
Int L [2] [max_line_station];
Int ls;
Int FS;
} Fixlinepara;
Int findfaststationsequence (fixlinepara * para, int N)
{
Int f [2] [max_line_station];
If (para = NULL) | (n <= 0 ))
{
Return-1;
}
F [0] [0] = para-> A [0] [0] + para-> E [0];
F [1] [0] = para-> A [1] [0] + para-> E [1];
For (Int J = 1; j <n; j ++)
{
If (f [0] [J-1] + para-> A [0] [J]) <= (F [1] [J-1] + para-> T [1] [J] + para-> A [0] [J])
{
F [0] [J] = f [0] [J-1] + para-> A [0] [J];
Para-> L [0] [J] = 1;
}
Else
{
F [0] [J] = f [1] [J-1] + para-> T [1] [J] + para-> A [0] [J];
Para-> L [0] [J] = 2;
}
If (f [1] [J-1] + para-> A [1] [J]) <= (F [0] [J-1] + para-> T [0] [J] + para-> A [1] [J])
{
F [1] [J] = f [1] [J-1] + para-> A [1] [J];
Para-> L [1] [J] = 2;
}
Else
{
F [1] [J] = f [0] [J-1] + para-> T [0] [J] + para-> A [1] [J];
Para-> L [1] [J] = 1;
}
}
If (F [0] [n-1] + para-> X [0] <= f [1] [n-1] + para-> X [1])
{
Para-> FS = f [0] [n-1] + para-> X [0];
Para-> ls = 1;
}
Else
{
Para-> FS = f [1] [n-1] + para-> X [1];
Para-> ls = 2;
}
Return 0;
}
After the solution is completed, para-> ls stores the assembly line numbers of the most used assembly stations, and para-> L stores the transfer records of the chassis on the two assembly lines, combined with para-> ls, the assembly sequence of the chassis can be pushed forward. Para-> FS storage shortest time. The function for printing the result is as follows:
Void printstations (fixlinepara * para, int N)
{
Int I = para-> ls;
Printf ("line % d, station % d/N", I, n );
For (Int J = n-1; j> 0; j --)
{
I = para-> L [I-1] [J];
Printf ("line % d, station % d/N", I, j );
}
}
The printed result is exactly the opposite of the actual Assembly order, because it is obtained through para-> ls forward recursion. The introduction to algorithms suggests that positive sequence results can be obtained through recursive methods, but it is not difficult to give algorithms because they are proposed as exercise questions. Here we will provide one:
Void printnextstations (fixlinepara * para, int N, int line)
{
If (n = 0)
{
Return;
}
Int I = para-> L [Line-1] [N];
Printnextstations (para, n-1, I );
Printf ("line % d, station % d/N", I, n );
}
Void printstations2 (fixlinepara * para, int N)
{
Int I = para-> ls;
Printnextstations (para, n-1, I );
Printf ("line % d, station % d/N", I, n );
}
The introduction to algorithms mentions that you can solve this problem through the exhaustive (recursive) method. Here we also provide a method to use the exhaustive search, it can still be used when the number of assembly stations is n small. Similarly, first define a Data Structure:
Typedef struct tagfixlineenumeratepara
{
Int A [2] [max_line_station];
Int T [2] [max_line_station];
Int e [2];
Int X [2];
Int L [max_line_station];
Int FS;
Int FL [max_line_station];
Int FFS;
} Fixlineenumeratepara;
Para-> L stores the assembly station sequence of an intermediate result during the search process. Para-> FS indicates the assembly time of the intermediate result, and para-> FL indicates the assembly station sequence of the final optimal solution, para-> FFS is the assembly time of the optimal solution.
Int findenumeratestationsequence (fixlineenumeratepara * para, int line, int station, int N)
{
If (station> = N) // The result is sorted first.
{
Para-> FS + = para-> A [Line] [Station-1];
Para-> FS + = para-> X [Line];
Para-> L [Station-1] = line + 1;
If (para-> FS <para-> FFS)
{
Para-> FFS = para-> FS;
Memmove (para-> FL, para-> L, N * sizeof (INT ));
}
Return 0;
}
Int curcost = para-> FS + para-> A [Line] [Station-1];
Para-> L [Station-1] = line + 1;
Station ++;
Para-> FS = curcost;
Findenumeratestationsequence (para, line, station, N );
Para-> FS = curcost;
Int nextline = (LINE + 1) % 2;
Para-> FS + = para-> T [Line] [Station-1];
Findenumeratestationsequence (para, nextline, station, N );
Return 0;
}
Int findfaststationsequenceenumerate (fixlineenumeratepara * para, int N)
{
Para-> FFS = 0x0fffffff;
Para-> FS = para-> E [0];
Findenumeratestationsequence (para, 0, 1, n );
Para-> FS = para-> E [1];
Findenumeratestationsequence (para, 1, 1, n );
Return 0;
}
The search is recursive according to the sequence of the assembly station, so the result is a positive sequence, and the function to print the result is very simple:
Void printstations3 (fixlineenumeratepara * para, int N)
{
For (INT I = 0; I <n; I ++)
{
Printf ("line % d, station % d/N", para-> FL [I], I + 1 );
}
}
The above is the solution of the two methods.