Мне нужно найти кластер в 2-м массиве. Это означает, что мне нужно найти наибольшее количество «1» в 2-мерном массиве. В массиве всего «0» и «1». Связанные числа могут быть все "1" в каждом направлении (8 направлений), например, эта матрица имеет кластер из 6

Пример: выход = 6

ma[] = { 1, 1, 0, 0, 0,
         1, 1, 0, 0, 0,
         0, 0, 1, 0, 0,    //because of diagonal
         0, 1, 0, 0, 1 };   // the last "1" should not be counted 

К сожалению, я понятия не имею, как это сделать. Вот мой последний код, с помощью которого я могу просто подсчитать все «1» в массиве 2d.

void cluster(int *mat, int rows, int cols) { 
    int i, j;
    int target = 0;
    printf("\n+++++++++++++++++++++++++++++++\nbiggst cluster\n\n");
    for(j = 0; j < cols; j++) { 
        for (i = 0; i < rows; i++) {
        if (mat[j*rows+i] == 1)
        target = target + 1;
        }
    }
printf("%d ", target);
}

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

Приветствует

1
WirJun 18 Ноя 2014 в 19:52
Ищите "заполнение заливкой"
 – 
Dmitri
18 Ноя 2014 в 19:59
Вы просто пытаетесь подсчитать все 1 в своем массиве?
 – 
Rizier123
18 Ноя 2014 в 20:06
Нет, я хочу найти наибольшую связанную сумму "1", пожалуйста, посмотрите еще раз на пример
 – 
WirJun
18 Ноя 2014 в 20:10
Не слишком ли опасно использовать такой рекурсивный алгоритм?
 – 
WirJun
18 Ноя 2014 в 20:13
Точнее, заполнение строки сканирования
 – 
Dmitri
18 Ноя 2014 в 20:17

3 ответа

Лучший ответ

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

Во-первых, некоторые пояснения к постановке вашей проблемы:

Следующий не определяет 2D-матрицу , он создается как одномерный массив с 20 элементами.

ma[] = { 1, 1, 0, 0, 0,
         1, 1, 0, 0, 0,
         0, 0, 1, 0, 0,    //because of diagonal
         0, 1, 0, 0, 1 };   // the last "1" should not be counted 

наибольшее количество единиц в двумерном массиве
Предположим, вы имеете в виду , количество соседних элементов со значением == 1 в массиве
и
цифры могут состоять из 1 в каждом направлении (8 направлений)
На самом деле есть только два направления в массиве C . (См. Объяснение ниже)

Для ясности измените некоторые определения:
1) определите кластер значений:
кластер - это 1 или несколько элементов массива, содержащих значение 1 и смежных с другим элементом массива в любом направлении. (см. комментарии к рядом ниже)
2) определите 2D-массив в C: 2D-массив в C - это область непрерывной памяти, в которой элементы массива расположены в виде основных строк:

Example: int array[4][5] = {{1,0,0,0,0},{0,1,0,0,0},{0,0,1,0,0},{0,0,0,1,0}};  

Концептуально выглядит так:

|1|0|0|0|0|    
|0|1|0|0|0|     
|0|0|1|0|0|    
|0|0|0|1|0|  //cluster of four

Но в памяти выглядит так:

|1|0|0|0|0|0|1|0|0|0|0|0|1|0|0|0|0|0|1|0|  //cluster of zero  (no "1" elements next to another)
|         |         |         |       |              
[0][0]    [1][0]    [2][0]    [3][0]  [3][4]      

Обратите внимание, что на самом деле Смежный имеет другую перспективу.

Таким образом, предполагаемое решение имеет мало общего со смежной памятью и больше связано с обозначением массива, например [i][j].

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

Учитывая int array[ROWS][COLS];

Вот тест на смежность : (используя наше определение)

array[m][n] примыкает к array[o][p], когда:

  • !((m == o) && (n == p)) //same element
  • (abs(m - o) <= 1) && (abs(n-p) <= 1)
  • ((m + o) < ROWS) &&((n + p) < COLS)

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

3
ryyker 1 Окт 2019 в 16:38
1
+1 за то, что заметил, что на самом деле это не матрица. Я не внимательно изучил код :-)
 – 
LSerni
18 Ноя 2014 в 22:51

Существуют более эффективные с точки зрения памяти методы, но: вы можете построить другую матрицу того же размера и инициализировать ее всеми нулями. Пусть это матрица B.

Начните сканирование первой матрицы A со счетчиком N, установленным на 1, и как только вы обнаружите в A «1» с «0» в B (т. Е. Aij = 1, Bij = 0), поместите его в list и инициализируйте M значением 0.

Затем, пока список не станет пустым:

  • выберите элемент из списка и увеличьте M.
  • посмотрите на его соседей (вам нужны только (x-1, y), (x + 1, y), (y + 1, x-1), (y + 1, x) и (y + 1, x + 1) )) и если у них Ax'y '= 1 и Bx'y' = 0, установите Bx'y 'в N и добавьте их в список.

Когда список пуст, вы нашли M элементов в кластере N, поэтому установите ClusterSize[N]=M.

Когда вы закончите, найдите максимальное значение ClusterSize, предположим, что это ClusterSize [K]; то все элементы, где Bij = K, принадлежат кластеру мощности M.

Алгоритм однократно обращается ко всем элементам матрицы. Вам нужно не более W * H / 4 элементов для массива Cluster (у вас не может быть более W * H / 4 кластеров с одним элементом без некоторых элементов, соединяющих и уменьшающих количество кластеров), не более W * H для AncillaryMatrix , и элементы W * H для List. Вы можете динамически распределять и перераспределять их по своему желанию, но, если не требуется для экономии памяти, я бы просто использовал пессимистическое значение.

Псевдокод:

int **AncillaryMatrix;

if (NULL == (AncillaryMatrix = malloc(sizeof(int *)*H))) {
    return ERROR_OUTOFMEMORY;
}
for (j = 0; j < H; j++) {
    if (NULL == (AncillaryMatrix[j] = malloc(sizeof(int)*W))) {
        while (--j) {
             free(AncillaryMatrix[j]); AncillaryMatrix[j] = NULL;
        }
        free(AncillaryMatrix); AncillaryMatrix = NULL;
        return ERROR_OUTOFMEMORY;
    }
    for (i = 0; i < W; i++) {
        AncillaryMatrix[j][i] = 0;
    }
}
N = 1;
for (j = 0; j < H; j++) {
    for (i = 0; i < W; i++) {
        if (0 == BaseMatrix[j][i]) {
            continue;
        }
        if (0 != AncillaryMatrix[j][i]) {
            continue;
        }
        if (0 == (Cluster[N] = FillMatrix(BaseMatrix, AncillaryMatrix, W, H, i, j, N)) {
            // Handle out of memory error.
        }
        N++;
    }
}
// Free ancillarymatrix, unless you need to know the items in the K-th cluster
j = H; while (j--) {
     free(AncillaryMatrix[j]); AncillaryMatrix[j] = NULL;
}
free(AncillaryMatrix); AncillaryMatrix = NULL;

// Find maximum value in Cluster[1..N-1].
// Cluster[0] is not used because "0" in AncillaryMatrix means "no cluster here"
// So the number of clusters is really N-1.
for (j = 1, i = 2; i < N; i++) {
     if (Cluster[i] > Cluster[j]) {
         j = i;
     }
}
// Largest cluster identified by j, has Cluster[j] members.

////

int FillMatrix(int **B, int **A, int W, int H, int i, int j, int N) {
    int M = 0;
    typedef struct Item { int x, int y } *List;
    if (null == (List = malloc(sizeof(Item)*W*H))) {
         return 0;
    }
    List[l].x = i;
    List[l].y = j;
    A[j][i] = N;
    l++;
    while (l) {
        l--; M++;
        int ii = List[l].x;
        int jj = List[l].y;
        // Add neighbours. NOTE: add code to handle case when jj or ii is 0
        // or jj is H-1 or ii is W-1.

        // check jj,ii-1 (could use a macro)
        if (B[jj][ii-1]) {
            if (0 == A[jj][ii-1]) {
                List[l].x = ii-1;
                List[l].y = jj;
                l++;
            }
        }
        CHECK(jj, ii+1)
        CHECK(jj+1, ii-1)
        CHECK(jj+1, ii)
        CHECK(jj+1, ii+1)
    }
    free(List); // List = NULL;
    return M;
}
1
LSerni 11 Июн 2019 в 16:14
Большое спасибо за ваш ответ. Я только начал практиковать язык C 2 месяца назад, и мне действительно интересно, как кто-то вроде меня должен решить такую ​​​​проблему.
 – 
WirJun
18 Ноя 2014 в 21:49

Ребята, я наконец нашел действительно простое решение этой проблемы, просто посмотрите сюда ...

void cluster(int rows, int cols) { 

    int ma4[4][5] = {{0, 1, 0, 0, 0}, // 1. Zeile
                     {1, 1, 0, 0, 0}, // 2. Zeile
                     {1, 1, 0, 1, 0}, // 3. Zeile
                     {0, 1, 0, 0, 0}};  // 4. Zeile
    int i = 0;
    int j = 0;
    int target = 0;
    printf("\n+++++++++++++++++++++++++++++++\nbiggst cluster\n\n");
    for(j = 0; j < cols; j++) { 
        for (i = 0; i < rows; i++) {
        if (ma4[j][i] == 1) {
        if (ma4[j-1][i] || ma4[j][i-1] || ma4[j+1][i] || ma4[j][i+1] || ma4[j-1][i-1] || ma4[j+1][i+1] || ma4[j-1][i+1] || ma4[j+1][i-1] == 1)
           target += 1;
            }
        }


    }
printf("%d ", target);
}
0
WirJun 11 Июн 2019 в 15:17
Вы уверены, что это сработает, если, скажем, нижний правый элемент равен 1? Вы будете читать за пределами самой матрицы.
 – 
LSerni
18 Ноя 2014 в 22:48