Я пытаюсь решить проблему динамического программирования, состоящую в том, чтобы иметь матрицу, найти отсортированную подматрицу максимального размера.

Я хочу использовать динамическое программирование, чтобы найти решение, но я не получаю правильный результат.

Моя программа состоит из двух методов: первый рекурсивно проверяет близость элементов к позиции, заданной параметром. Затем во втором методе я вызываю предыдущий, чтобы найти максимальный порядок подматрицы, но он не возвращает правильный результат.

Например, для этой матрицы и вызова класса с новым Решением (5, 6)

                10, 1, 4, 1, 4, 0
                1, 2, 10, 6, 2, 1
                6, 7, 20, 10, 1, 2
                9, 10, 23, 0, 3, 5
                10, 11, 24, 1, 0, 2

Он должен вернуть 4. Вот мой код:

import java.util.Scanner;

public class Solution {
    private int[][] mat;
    Scanner sc = new Scanner(System.in);
    int n, m;


    public Solution(int n, int m) {
        this.n = n;
        this.m = m;
        mat = new int[n][m];
        for(int i = 0; i < n; i++)
            for(int j = 0; j < m; j++)
                mat[i][j] = sc.nextInt();
        for(int i = 0; i < n; i++) {
            System.out.println();
            for(int j = 0; j < m; j++)
                System.out.print(mat[i][j] + "\t");
        }
    }

    public void call() {
        int sol = maxSortedMatrix(mat);
        System.out.println("Matrix of order " + sol);
    }

    private int nearElements(int i, int j, int[][] mat, int[][] maxLongi) {
        // basically recursively check surrounding elements. If they are exist and smaller than
        // current element, we should consider it as the longest increasing sub sequence. However if we
        // already check one element, the value corresponding to that index pair should no longer be zero,
        // thus no need to recursively calculate that value again.
        if (maxLongi[i][j] == 0) {
        // have not been visited before, need recursive calculation
            // have not recursively checking.
            int length = 1;
            // up
            if (i - 1 > -1 && mat[i][j] > mat[i - 1][j]) {
                length = Math.max(length, 1 + nearElements(i - 1, j, mat, maxLongi));
            }
            // down
            if (i + 1 < mat.length && mat[i][j] > mat[i + 1][j]) {
                length = Math.max(length, 1 + nearElements(i + 1, j, mat, maxLongi));
            }
            // left
            if (j - 1 > -1 && mat[i][j] > mat[i][j - 1]) {
                length = Math.max(length, 1 + nearElements(i, j - 1, mat, maxLongi));
            }

            // right
            if (j + 1 < mat[0].length && mat[i][j] > mat[i][j + 1]) {
                length = Math.max(length, 1 + nearElements(i, j + 1, mat, maxLongi));
            }
            maxLongi[i][j] = length; // setting maxLenTailing value here to avoid additional recurssively checking
            return length;
        }
        return maxLongi[i][j];
    }

    private int maxSortedMatrix(int[][] mat) {
        if (mat == null || mat.length == 0 || mat[0] == null || mat[0].length == 0) {
            return 0;
        }
        int[][] maxLength = new int[n][m];
        // store the max length of increasing subsequence that ending at i and j.
        int max = 0;
        // top left to bottom right
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < m; ++j) {
// scan every element in the matrix.
                maxLength[i][j] = nearElements(i, j, mat, maxLength);
                max = Math.max(max, maxLength[i][j]);
            }
        }
        return max;
    }
}
1
DDN 26 Ноя 2016 в 20:58

2 ответа

Лучший ответ

Ответ для квадратной подматрицы может быть несколько проще вычислить, чем для обычного прямоугольника. В Python мы можем воспользоваться небольшим трюком с двойным сравнением (общее обсуждение см. В ответе ruakh):

a = [
  [10, 1, 4, 1, 4, 0],
  [ 1, 2,10, 6, 2, 1],
  [ 6, 7,20,10, 1, 2],
  [ 9,10,23, 0, 3, 5],
  [10,11,24, 1, 0, 2]
]

m = [ [1] * len(a[0]) for i in range(0,len(a)) ]

for i in range(1,len(a)):
  for j in range(1,len(a[0])):
    if a[i-1][j-1] <= a[i][j-1] <= a[i][j] and a[i-1][j-1] <= a[i-1][j] <= a[i][j]:
      m[i][j] = min(m[i-1][j],m[i][j-1],m[i-1][j-1]) + 1

for i in m:
  print i

"""
[1, 1, 1, 1, 1, 1]
[1, 1, 2, 1, 1, 1]
[1, 2, 2, 1, 1, 1]
[1, 2, 3, 1, 1, 2]
[1, 2, 3, 1, 1, 1]
"""
0
גלעד ברקן 27 Ноя 2016 в 15:41

Проблема в том, что ваш алгоритм неверен; вам нужен совсем другой.

Ваш алгоритм вычисляет длину самого длинного возрастающего пути через матрицу, а именно 8:

              ,   ,   ,   ,   ,  0
              ,   ,   ,  6,  2,  1
              ,   , 20, 10,   ,  
              ,   , 23,   ,   ,  
              ,   , 24,   ,   ,  

Он делает это, вычисляя для каждого элемента в матрице длину самого длинного возрастающего пути, который заканчивается в этом элементе:

             2,  1,  2,  1,  4,  1
             1,  2,  5,  4,  3,  2
             2,  3,  6,  5,  1,  3
             3,  4,  7,  1,  2,  4
             4,  5,  8,  2,  1,  2

А затем выбрать наибольшую такую длину (а именно 8).

Вместо этого вам нужно вычислить для каждого элемента в матрице размер самой большой отсортированной квадратной подматрицы, в которой этот элемент находится внизу справа:

             1,  1,  1,  1,  1,  1 
             1,  1,  2,  1,  1,  1 
             1,  2,  2,  1,  1,  1 
             1,  2,  3,  1,  1,  2 
             1,  2,  3,  1,  1,  1 

А затем выберите наибольший такой размер (а именно 3).

Обратите внимание, что, в отличие от проблемы с самым длинным возрастающим путем, здесь не требуется рекурсия и мемоизация; скорее, это чисто проблема динамического программирования. Вы можете просто работать сверху вниз по матрице и слева направо, вычисляя каждый подрезультат в зависимости только от подрезультатов, которые вы уже вычислили. (Я заметил, что вы пометили этот вопрос тегом [динамическое программирование], поэтому я предполагаю, что это то, что ваш профессор хочет, чтобы вы сделали.)

2
ruakh 28 Ноя 2016 в 01:06