矩阵连续n个数字的最大乘积

时间:2014-02-04 01:04:38

标签: c++ math matrix computation

您好,我正在尝试编写一个小程序。问题是如果我给出任何矩阵大小(这个例子只是说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矢量中。我对程序的工作原理并不太挑剔(蛮力很好),到目前为止我知道我必须至少有两个嵌套的for循环来遍历矩阵的每个凝视位置但是我没有找到了当前的答案是成功的。任何建议都会有所帮助,谢谢。

3 个答案:

答案 0 :(得分:1)

如果你坚持使用蛮力,那么正如你所说,你需要遍历所有[x,y], 这将是行的起点。 通过这些,您可以在所有方向上迭代k个相邻元素。 您可以将方向存储为数组中的向量。 这将在O(k n^2)中运行。

对于n x n矩阵并在行中查找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 :(得分:1)

假设我们有s x t矩阵(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
            }
        }   
    }   
}

答案 2 :(得分: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;
}

结果:

RES:42

7,2,3,

RUN SUCCESSFUL(总时间:113ms)