There is such an article, the results of which I want to use: http://www.geeksforgeeks.org/dynamic-programming-set-8-matrix-chain-multiplication/

The program from there works correctly: https://ideone.com/5ezfkL

And here is the result of the work of the same program that I am trying to run from VS 2010:

// ΠœΠ°Ρ‚Ρ€ΠΈΡ†Π° Ai ΠΈΠΌΠ΅Π΅Ρ‚ Ρ€Π°Π·ΠΌΠ΅Ρ€Π½ΠΎΡΡ‚ΡŒ p[i-1] xp[i] для i = 1..n int MatrixChainOrder(int p[], int n) { /* Для простоты ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹, Π² m[][] ΠΎΠ΄Π½Π° Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ°Π½Ρ строка ΠΈ ΠΎΠ΄ΠΈΠ½ Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹ΠΉ столбСц]. НулСвая строка ΠΈ Π½ΡƒΠ»Π΅Π²ΠΎΠΉ столбСц Π² m[][] Π½Π΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‚ΡΡ */ int **m = new int* [n]; for(int i = 0; i < n; i++) m[i] = new int [n]; int i, j, k, L, q; /* m[i,j] = минимальноС число скалярных ΡƒΠΌΠ½ΠΎΠΆΠ΅Π½ΠΈΠΉ, Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎΠ΅ для вычислСния ΠΌΠ°Ρ‚Ρ€ΠΈΡ†Ρ‹ A[i]A[i+1]...A[j] = A[i..j], Π³Π΄Π΅ Ρ€Π°Π·ΠΌΠ΅Ρ€Π½ΠΎΡΡ‚ΡŒ A[i] Ρ€Π°Π²Π½Π° p[i-1] xp[i] */ // Π‘Ρ‚ΠΎΠΈΠΌΠΎΡΡ‚ΡŒ Ρ€Π°Π²Π½Π° Π½ΡƒΠ»ΡŽ, ΠΊΠΎΠ³Π΄Π° ΡƒΠΌΠ½ΠΎΠΆΠ°Π΅ΠΌ ΠΎΠ΄Π½Ρƒ ΠΌΠ°Ρ‚Ρ€ΠΈΡ†Ρƒ for (i = 1; i < n; i++) m[i][i] = 0; // L - Π΄Π»ΠΈΠ½Π° Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠΈ for (L=2; L<n; L++) { for (i=1; i<=n-L+1; i++) { j = i+L-1; m[i][j] = INT_MAX; for (k=i; k<=j-1; k++) { // q = ΡΡ‚ΠΎΠΈΠΌΠΎΡΡ‚ΡŒ/скалярныС умноТСния q = m[i][k] + m[k+1][j] + p[i-1]*p[k]*p[j]; if (q < m[i][j]) m[i][j] = q; } } } return m[1][n-1]; } 

Example of running the program:

 int main(){ const int n = 10; int p[n] = {10, 50, 30, 7, 25, 60, 15, 80, 55, 30}; int cost = 0; cost = MatrixChainOrder(p, n); //std::cout << "Solution for m and s: " << std::endl; std::cout << "min cost: " << cost << std::endl; int pause; std::cin >> pause; } 

In the debugger, I could not figure out anything: at the last iterations of filling the table, the program suddenly crashes with an access violation, and a file with locks opens. Indexes, as I have noticed, do not go beyond the permissible limits.

And also: in the function we have a memory leak, because the dynamic array is not deleted. But you cannot delete it, because you need to return the value of its cell. What can be done with this?

    1 answer 1

    Algorithm is invalid.

    Consider your example call with n = 10 . Consider a cycle

     for (int L=2; L<n; L++) { for (int i=1; i<=n-L+1; i++) { int j = i+L-1; m[i][j] = INT_MAX; for (int k=i; k<=j-1; k++) { // q = ΡΡ‚ΠΎΠΈΠΌΠΎΡΡ‚ΡŒ/скалярныС умноТСния int q = m[i][k] + m[k+1][j] + p[i-1]*p[k]*p[j]; if (q < m[i][j]) m[i][j] = q; } } } 

    Let at the first iteration L = 2 . Then i changes from 1 to 10 - 2 + 1 = 9 . When i = 9 , j = i + 2 - 1 = 10 . Calculating q refers to p[j] , that is, a non-existent index. The same applies to the expression m[i][j] .


    Regarding the dynamic array - why not copy the value of the cell before returning from a function to an auxiliary variable, delete the array, and return the saved value?


    Corrected indexing. I have such a code that runs without any problems:

     int MatrixChainOrder(int p[], int n) { int **m = new int*[n]; for (int i = 0; i < n; i++) m[i] = new int [n]; for (int i = 0; i < n; i++) m[i][i] = 0; // L - Π΄Π»ΠΈΠ½Π° Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠΈ // !! Ρƒ ΠšΠΎΡ€ΠΌΠ΅Π½Π° Ρ‚ΡƒΡ‚ <= for (int L = 2; L <= n; L++) { for (int i = 1; i <= n - L + 1; i++) { int j = i + L - 1; m[i - 1][j - 1] = INT_MAX; for (int k = i; k <= j - 1; k++) { // q = ΡΡ‚ΠΎΠΈΠΌΠΎΡΡ‚ΡŒ/скалярныС умноТСния int q = m[i - 1][k - 1] + m[k][j - 1] + p[i - 1] * p[k] * p[j]; if (q < m[i - 1][j - 1]) m[i - 1][j - 1] = q; } } } int result = m[0][n - 1]; for (int i = 0; i < n; i++) delete[] m[i]; delete[] m; return result; } int main() { const int n = 10; // Π΄ΠΎΠ±Π°Π²ΠΈΠ» Π΅Ρ‰Ρ‘ ΠΎΠ΄Π½ΠΎ значСния, Ρƒ ΠšΠΎΡ€ΠΌΠ΅Π½Π° Ρ‚Π°ΠΌ [p0..pn] int p[n + 1] = {10, 50, 30, 7, 25, 60, 15, 80, 55, 30, 99}; int cost = MatrixChainOrder(p, n); ... 

    Check if result is considered correct.


    Perhaps it would be more correct to index from scratch. Rewrote the central piece, reducing by 1 the values ​​of i , j , k :

     int MatrixChainOrder(int p[], int n) { int **m = new int*[n]; for (int i = 0; i < n; i++) m[i] = new int [n]; for (int i = 0; i < n; i++) m[i][i] = 0; // L - Π΄Π»ΠΈΠ½Π° Ρ†Π΅ΠΏΠΎΡ‡ΠΊΠΈ for (int L = 2; L <= n; L++) { for (int i = 0; i < n - L + 1; i++) { int j = i + L - 1; m[i][j] = INT_MAX; for (int k = i; k <= j - 1; k++) { // q = ΡΡ‚ΠΎΠΈΠΌΠΎΡΡ‚ΡŒ/скалярныС умноТСния int q = m[i][k] + m[k + 1][j] + p[i] * p[k + 1] * p[j + 1]; if (q < m[i][j]) m[i][j] = q; } } } int result = m[0][n - 1]; for (int i = 0; i < n; i++) delete[] m[i]; delete[] m; return result; } 
    • It looks like a fatal error that cannot be fixed by adjusting the range of indexes. And it is at Cormen so, the implementation is almost verbatim. Although maybe this condition i <= n-L + 1 just guarantees that there is no way out of the array. - typemoon
    • @typemoon: Maybe Cormen has arrays numbered from one? - VladD
    • Yes, from one. - typemoon
    • Oh, that's it! Well then maybe an error in the transfer of the algorithm? It makes sense to take the algorithm as it is, and simply subtract one at each indexing. - VladD
    • I tried to do exactly that first. It is strange that this method does not work. After all, indices are not important if my matrices m and s are inside other large matrices. For example, the matrix m 7x7 is in the middle of the matrix 20x20. Then you can not be afraid to go beyond the arrays The code turned out this way. ideone.com/fPxrFb - typemoon