Как найти регион, который имеет максимальное количество единиц в C?

У меня есть 2D матрица 500x500, которая содержит значения 0 или 1. Есть ли способ найти высококонцентрированную область, которая содержит значение 1, или, скажем, область с максимальным числом не равным 1? Я пытался обойти всю 2D матрицу с меньшим (Массив размером 50x50), но это занимает очень много времени. Есть ли какой-либо другой способ, который является более эффективным и занимает меньше времени выполнения. Я должен сделать это в программировании на Си.

2 ответа

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

void subarray(char array[500][500], int *x, int *y, int *pmax)
{
    int i, j, k, l;
    int max = -1;

    for (i = 0; i < 450; i++) {
        for (j = 0; j < 450; j++) {
            int n = 0;

            for (k = 0; k < 50; k++) {
                for (l = 0; l < 50; l++) {
                    n += array[i + k][j + l];
                }
            }

            if (n > max) {
                max = n;
                *x = i;
                *y = j;
                *pmax = max;
            }
        }
    }
}

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

Если вы хотите рассчитать количество единиц в прямоугольнике с верхней левой точкой (x0, y0) и с правой нижней точкой (x1, y1), ты получаешь:

n = count[y1][yy1] + count[y0][x0] - count[y0][x1] - count[y1][x0]

Так:

void subarraye(char array[500][500], int *x, int *y, int *pmax)
{
    int count[500][500];
    int i, j;
    int max = -1;

    count[0][0] = array[0][0];

    for (i = 1; i < 450; i++) {
        count[i][0] = count[i - 1][0] + array[i][0];
    }

    for (i = 1; i < 450; i++) {
        count[0][i] = count[0][i - 1] + array[0][i];
    }

    for (i = 1; i < 500; i++) {
        for (j = 1; j < 500; j++) {
            count[i][j] = count[i - 1][j] + count[i][j - 1]
                        - count[i - 1][j - 1] + array[i][j];
        }
    }       

    for (i = 0; i < 450; i++) {
        for (j = 0; j < 450; j++) {
            int n = count[i + 50][j + 50] + count[i][j]
                  - count[i][j + 50] - count[i + 50][j];

            if (n > max) {
                max = n;
                *x = i + 1;
                *y = j + 1;
                *pmax = n;
            }
        }
    }
}

Индексы отключены на один, потому что количество единиц до исключительной границы (x, y) хранятся в (x - 1, y - 1) и верхний и левый ряд прямоугольников нулевой площади опущены.

Для повышения эффективности вы можете использовать параллельную технику. Вы можете использовать для этого, например, CUDA.

Также неплохо использовать алгоритм конкретного соседа и вычислять наиболее плотное пространство.

Другие вопросы по тегам