Матрица наибольшего произведения из n чисел подряд

0

Привет, у меня проблемы с небольшой программой, которую я пытаюсь написать. Проблема в том, что если мне задан размер матрицы (давайте просто скажем 4x4 для этого примера), найдите наибольшее произведение n чисел в строке (скажем, n = 3). 3 числа в строке могут быть горизонтальными, вертикальными или диагональными. Таким образом, матрица:

1 1 2 5
1 5 2 4
1 7 2 3
1 8 2 1

Если n было равно 3, то самым большим продуктом было бы 280 (5 * 7 * 8). Теперь моя матрица загружена в 2D-вектор. Я не слишком придирчив к тому, как работает программа (грубая сила в порядке), до сих пор я знаю, что мне нужно будет иметь по крайней мере два вложенных цикла, чтобы пройти через каждое смотрящее расположение матрицы, но у меня нет удалось найти текущий ответ. Любой совет поможет, спасибо.

  • 0
    числа могут быть только смежными или любой комбинацией n в строке или столбце?
  • 0
    рядом должно быть n чисел подряд (а не ряд, как в строке матрицы)
Теги:
math
matrix
computation

3 ответа

1
Лучший ответ

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

if (currN == N) { // compute full product first time
    while (currn) {
         product *= (*it3++);
          --currn;
    }
 } else {          // rolling computation
     product *= (*(it3 + n - 1)) / (*(it3 - 1));
     it3 += n;
 }

Вы должны завершить это, чтобы обрабатывать также столбцы:

заполняющая матрица:

#include <cstdio>
#include <vector>
#include <algorithm>
#include <iterator>
#include <iostream>
using namespace std;

typedef vector< vector< int> > Matrix;
typedef Matrix::iterator outIt;
typedef vector< int>::iterator inIt;

void fillMatrix( Matrix& matrix) {
    outIt it = matrix.begin();
    (*it).push_back( 1);
    (*it).push_back( 1);
    (*it).push_back( 2);
    (*it).push_back( 5);
    ++it;
    (*it).push_back( 1);
    (*it).push_back( 5);
    (*it).push_back( 2);
    (*it).push_back( 4);
    ++it;
    (*it).push_back( 1);
    (*it).push_back( 7);
    (*it).push_back( 2);
    (*it).push_back( 3);
    ++it;
    (*it).push_back( 1);
    (*it).push_back( 8);
    (*it).push_back( 2);
    (*it).push_back( 1);
}

распечатать матрицу и найти максимальный продукт в строках:

void printMatrix( Matrix& matrix) {
    outIt it = matrix.begin();
    while ( it != matrix.end()) {
        inIt it2 = (*it).begin();
        while ( it2 != (*it).end()) {
            printf( "%d", *it2);
            ++it2;
        }
        printf( "\n");
        ++it;
    }
}

/**
 * 
 * @param matrix
 * Largest product in row using rolling multiplication
 * @param n number of factors
 * @param v factors of largest product
 * @return largest product
 */
int largestProductInRow( Matrix& matrix, int n, vector< int>& v) {
    if ( n > matrix.size()) return -1;
    int res = 0;
    int N = matrix.size() - n + 1; // number of products in row (or column)
    /* search in rows */
    outIt it = matrix.begin();
    while (it != matrix.end()) {
        inIt it2 = (*it).begin();
        int currN = N;
        int product = 1;
        while (currN) {       // rolling product calculation
            inIt it3 = it2;
            int currn = n;
            if (currN == N) { // compute full product first time
                while (currn) {
                    product *= (*it3++);
                    --currn;
                }
            } else {          // rolling computation
                product *= (*(it3 + n - 1)) / (*(it3 - 1));
                it3 += n;
            }
            if (product > res) {
                res = product;
                copy(it3 - n, it3, v.begin());
            }
            --currN;
            ++it2;
        }
        ++it;
    }
    return res;
}

Применение:

/*
 * 
 */
int main(int argc, char** argv) {

    Matrix matrix( 4, vector< int>());
    fillMatrix( matrix);
    printMatrix( matrix);
    vector< int> v(3);
    int res = largestProductInRow( matrix, 3, v);
    printf( "res:%d\n", res);
    copy( v.begin(), v.end(), ostream_iterator<int>(cout, ","));
    return 0;
}

результат:

разрешение: 42

7,2,3,

RUN SUCCESSFUL (общее время: 113 мс)

1

Если вы настаиваете на грубой силе, то, как вы сказали, вам нужно перебрать все [x,y], которые будут отправными точками строк. Из них вы можете перебирать k смежных элементов во всех направлениях. Вы можете сохранить направления в виде векторов в массиве. Это будет работать в O(kn^2).

Для nxn матрицы и поиска k элементов в строке C-подобный псевдокод будет выглядеть так (обратите внимание, что для простоты нет ограничений для проверки):

// define an array of directions as [x,y] unit vectors
// you only need to check in 4 directions, other 4 are the same, just reversed
int[4][2] dirs = {{1,0}, {1,1}, {0,1}, {-1,1}};

// iterate over all starting positions
for (x = 0; x < n; ++x) {
    for (y = 0; y < n; ++y) {
        // iterate over all directions
        for (d = 0; d < 4; ++d) {
            result = 1;
            // iterate over elements in row starting at [x,y]
            // going in direction dirs[d]
            for (i = 0; i < k; ++i) {
                // multiply current result by the element,
                // which is i places far from the beginning [x,y]
                // in the direction pointed by dirs[d]
                new_x = x + i * dirs[d][0];
                new_y = y + i * dirs[d][1];
                // you need to check the bounds, i'm not writing it here
                // if new_x or new_y are outside of the matrix
                // then continue with next direction
                result *= matrix[new_x][new_y];
            }
            if (result > max) {
                max = result;
            }
        }
    }
}

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

Во время ходьбы вы держите продукт, умножая его на число, которое вы получили, и делясь на число, которое вы оставили k шагов назад. Таким образом, с определенными ограничениями, конечно, продукт всегда является произведением последних k чисел, поэтому, если текущий продукт больше, чем максимальный, просто пусть max = product. Это всегда выполняется в O(n^2).

1

Допустим, у нас есть sxt-матрица (s-столбцы и t строк).

int res = 0;
if(s >= n)
{
    for (int r = 0; r < t; ++r) // for each row
    {
        for (int i = 0; i <= s-n; ++i)  //moving through the row
        {
            int mul = m[i][0];
            for (int j = 1; j < n; ++j) //calculating product in a row
            {
                mul*=m[i][j];
            }
            if(mul > res)
            {
                res = mul;
                //save i, j here if needed
            }
        }   
    }
}


if(t >= n)
{
    for (int c = 0; c < s; ++c) // for each column
    {
        for (int i = 0; i <= t-n; ++i)  //moving through the column
        {
            int mul = m[0][i];
            for (int j = 1; j < n; ++j) //calculating product in a column
            {
                mul*=m[j][i];
            }
            if(mul > res)
            {
                res = mul;
                //save i, j here if needed
            }
        }   
    }   
}

Ещё вопросы

Сообщество Overcoder
Наверх
Меню