2010-02-20 20 views
6

मेरे पास एन से एन * एन मैट्रिक्स (एन = 2 से 10000) संख्याएं हैं जो 0 से 1000 तक हो सकती हैं। मुझे सबसे बड़ा (आयताकार) सबमिट्रिक्स कैसे मिल सकता है जिसमें एक ही संख्या होती है?सबसे बड़ा सबमिट्रिक्स एल्गोरिदम

उदाहरण:

 1 2 3 4 5 
    -- -- -- -- -- 
1 | 10 9 9 9 80 
2 | 5 9 9 9 10 
3 | 85 86 54 45 45 
4 | 15 21 5 1 0 
5 | 5 6 88 11 10 

उत्पादन submatrix के क्षेत्र, अपने ऊपरी बाएँ तत्व का 1 आधारित निर्देशांक द्वारा पीछा किया जाना चाहिए। उदाहरण के लिए, यह (6, 2, 1) होगा क्योंकि कॉलम 2 में स्थित छह 9 रों देखते हैं, पंक्ति 1.

+2

यदि यह होमवर्क है काम कर हाइलाइटिंग पाने के लिए नहीं कर रहा हूँ, तो कृपया स्पष्ट करें। –

+2

गृहकार्य? आपको समस्या को विस्तार से वर्णन करने की आवश्यकता है उदा। क्या नकारात्मक संख्याएं हैं? मुझे एक गतिशील प्रोग्रामिंग समस्या की तरह लग रहा है। – dirkgently

+1

सबसे बड़ा परिभाषित करें: तत्वों की संख्या? सबसे बड़ी चौड़ाई? सबसे बड़ी ऊंचाई? सबसे बड़ी राशि? – Patrick

उत्तर

0

इस पर कार्य चल रहा

मैं इस समस्या के बारे में सोचा है और मुझे लगता है कि मैं एक हो सकता है O(w*h) एल्गोरिदम।

विचार इस प्रकार है:

  • किसी भी (i,j) के लिए स्तंभ j(i,j) से शुरू में एक ही मूल्य के साथ कोशिकाओं की सबसे बड़ी संख्या की गणना। इस मान को heights[i][j] के रूप में स्टोर करें। सभी उप मैट्रिक्स जिसका height > heights[i][j] जे
    • पॉप:
    • सभी पंक्ति के लिए उप मैट्रिक्स (एक LIFO)
    • के एक खाली वेक्टर बनाएँ: मैं
        सभी स्तंभ के लिए
      • । क्योंकि ऊंचाई के साथ submatrix>heights[i][j] इस सेल पर जारी नहीं रख सकते
      • धक्का एक submatrix (i,j,heights[i][j]) जहां j है द्वारा परिभाषित farest समन्वय जहां हम ऊंचाई की एक submatrix फिट कर सकते हैं: heights[i][j]
      • अद्यतन वर्तमान अधिकतम उप मैट्रिक्स

मुश्किल हिस्सा आंतरिक पाश में है। मैं प्रत्येक सेल के लिए औसत पर O(1) सुनिश्चित करने के लिए अधिकतम सबविंडो एल्गोरिदम के समान कुछ उपयोग करता हूं।

मैं एक सबूत तैयार करने की कोशिश करूंगा लेकिन इस बीच यहां कोड है।

#include <algorithm> 
#include <iterator> 
#include <iostream> 
#include <ostream> 
#include <vector> 

typedef std::vector<int> row_t; 
typedef std::vector<row_t> matrix_t; 

std::size_t height(matrix_t const& M) { return M.size(); } 
std::size_t width (matrix_t const& M) { return M.size() ? M[0].size() : 0u; } 

std::ostream& operator<<(std::ostream& out, matrix_t const& M) { 
    for(unsigned i=0; i<height(M); ++i) { 
    std::copy(begin(M[i]), end(M[i]), 
      std::ostream_iterator<int>(out, ", ")); 
    out << std::endl; 
    } 
    return out; 
} 

struct sub_matrix_t { 
    int i, j, h, w; 
    sub_matrix_t(): i(0),j(0),h(0),w(1) {} 
    sub_matrix_t(int i_,int j_,int h_,int w_):i(i_),j(j_),h(h_),w(w_) {} 
    bool operator<(sub_matrix_t const& rhs) const { return (w*h)<(rhs.w*rhs.h); } 
}; 


// Pop all sub_matrix from the vector keeping only those with an height 
// inferior to the passed height. 
// Compute the max sub matrix while removing sub matrix with height > h 
void pop_sub_m(std::vector<sub_matrix_t>& subs, 
      int i, int j, int h, sub_matrix_t& max_m) { 

    sub_matrix_t sub_m(i, j, h, 1); 

    while(subs.size() && subs.back().h >= h) { 
    sub_m = subs.back(); 
    subs.pop_back(); 
    sub_m.w = j-sub_m.j; 
    max_m = std::max(max_m, sub_m); 
    } 

    // Now sub_m.{i,j} is updated to the farest coordinates where there is a 
    // submatrix with heights >= h 

    // If we don't cut the current height (because we changed value) update 
    // the current max submatrix 
    if(h > 0) { 
    sub_m.h = h; 
    sub_m.w = j-sub_m.j+1; 
    max_m = std::max(max_m, sub_m); 
    subs.push_back(sub_m); 
    } 
} 

void push_sub_m(std::vector<sub_matrix_t>& subs, 
     int i, int j, int h, sub_matrix_t& max_m) { 
    if(subs.empty() || subs.back().h < h) 
    subs.emplace_back(i, j, h, 1); 
} 

void solve(matrix_t const& M, sub_matrix_t& max_m) { 
    // Initialize answer suitable for an empty matrix 
    max_m = sub_matrix_t(); 
    if(height(M) == 0 || width(M) == 0) return; 

    // 1) Compute the heights of columns of the same values 
    matrix_t heights(height(M), row_t(width(M), 1)); 
    for(unsigned i=height(M)-1; i>0; --i) 
    for(unsigned j=0; j<width(M); ++j) 
     if(M[i-1][j]==M[i][j]) 
    heights[i-1][j] = heights[i][j]+1; 

    // 2) Run through all columns heights to compute local sub matrices 
    std::vector<sub_matrix_t> subs; 
    for(int i=height(M)-1; i>=0; --i) { 
    push_sub_m(subs, i, 0, heights[i][0], max_m); 
    for(unsigned j=1; j<width(M); ++j) { 
     bool same_val = (M[i][j]==M[i][j-1]); 
     int pop_height = (same_val) ? heights[i][j] : 0; 
     int pop_j  = (same_val) ? j    : j-1; 
     pop_sub_m (subs, i, pop_j, pop_height, max_m); 
     push_sub_m(subs, i, j,  heights[i][j], max_m); 
    } 
    pop_sub_m(subs, i, width(M)-1, 0, max_m); 
    } 
} 

matrix_t M1{ 
    {10, 9, 9, 9, 80}, 
    { 5, 9, 9, 9, 10}, 
    {85, 86, 54, 45, 45}, 
    {15, 21, 5, 1, 0}, 
    { 5, 6, 88, 11, 10}, 
}; 

matrix_t M2{ 
    {10, 19, 9, 29, 80}, 
    { 5, 9, 9, 9, 10}, 
    { 9, 9, 54, 45, 45}, 
    { 9, 9, 5, 1, 0}, 
    { 5, 6, 88, 11, 10}, 
}; 


int main() { 
    sub_matrix_t answer; 

    std::cout << M1 << std::endl; 
    solve(M1, answer); 
    std::cout << '(' << (answer.w*answer.h) 
     << ',' << (answer.j+1) << ',' << (answer.i+1) << ')' 
     << std::endl; 

    answer = sub_matrix_t(); 
    std::cout << M2 << std::endl; 
    solve(M2, answer); 
    std::cout << '(' << (answer.w*answer.h) 
     << ',' << (answer.j+1) << ',' << (answer.i+1) << ')' 
     << std::endl; 
} 
0

यह एक आदेश पंक्तियाँ * कॉलम समाधान

यह काम करता है द्वारा

  • सरणी के तल पर शुरू करने, और एक कॉलम में प्रत्येक संख्या यह मैच नीचे कितने आइटम का निर्धारण है। यह ओ (एमएन) समय (बहुत ही मामूली) में किया जाता है
  • फिर यह नीचे से नीचे & दाएं से दाएं ओर जाता है और देखता है कि कोई दिया गया नंबर बाईं ओर संख्या से मेल खाता है या नहीं। यदि ऐसा है, तो यह ट्रैक करता है कि कैसे ऊंचाई एक दूसरे से संबंधित आयताकार आकार

ट्रैक करने के लिए एक दूसरे से संबंधित है, यहां एक काम कर रहे पायथन कार्यान्वयन है।के बाद से मैं क्षमा याचना यकीन है कि कैसे वाक्य रचना

# this program finds the largest area in an array where all the elements have the same value 
# It solves in O(rows * columns) time using O(rows*columns) space using dynamic programming 




def max_area_subarray(array): 

    rows = len(array) 
    if (rows == 0): 
     return [[]] 
    columns = len(array[0]) 


    # initialize a blank new array 
    # this will hold max elements of the same value in a column 
    new_array = [] 
    for i in range(0,rows-1): 
     new_array.append([0] * columns) 

    # start with the bottom row, these all of 1 element of the same type 
    # below them, including themselves 
    new_array.append([1] * columns) 

    # go from the second to bottom row up, finding how many contiguous 
    # elements of the same type there are 
    for i in range(rows-2,-1,-1): 
     for j in range(columns-1,-1,-1): 
      if (array[i][j] == array[i+1][j]): 
       new_array[i][j] = new_array[i+1][j]+1 
      else: 
       new_array[i][j] = 1 


    # go left to right and match up the max areas 
    max_area = 0 
    top = 0 
    bottom = 0 
    left = 0 
    right = 0 
    for i in range(0,rows): 
     running_height =[[0,0,0]] 
     for j in range(0,columns): 

      matched = False 
      if (j > 0): # if this isn't the leftmost column 
       if (array[i][j] == array[i][j-1]): 
        # this matches the array to the left 
        # keep track of if this is a longer column, shorter column, or same as 
        # the one on the left 
        matched = True 

        while(new_array[i][j] < running_height[-1][0]): 
         # this is less than the one on the left, pop that running 
         # height from the list, and add it's columns to the smaller 
         # running height below it 
         if (running_height[-1][1] > max_area): 
          max_area = running_height[-1][1] 
          top = i 
          right = j-1 
          bottom = i + running_height[-1][0]-1 
          left = j - running_height[-1][2] 

         previous_column = running_height.pop() 
         num_columns = previous_column[2] 

         if (len(running_height) > 0): 
          running_height[-1][1] += running_height[-1][0] * (num_columns) 
          running_height[-1][2] += num_columns 

         else: 
          # for instance, if we have heights 2,2,1 
          # this will trigger on the 1 after we pop the 2 out, and save the current 
          # height of 1, the running area of 3, and running columsn of 3 
          running_height.append([new_array[i][j],new_array[i][j]*(num_columns),num_columns]) 


        if (new_array[i][j] > running_height[-1][0]): 
         # longer then the one on the left 
         # append this height and area 
         running_height.append([new_array[i][j],new_array[i][j],1]) 
        elif (new_array[i][j] == running_height[-1][0]): 
         # same as the one on the left, add this area to the one on the left 
         running_height[-1][1] += new_array[i][j] 
         running_height[-1][2] += 1 



      if (matched == False or j == columns -1): 
       while(running_height): 
        # unwind the maximums & see if this is the new max area 
        if (running_height[-1][1] > max_area): 
         max_area = running_height[-1][1] 
         top = i 
         right = j 
         bottom = i + running_height[-1][0]-1 
         left = j - running_height[-1][2]+1 

         # this wasn't a match, so move everything one bay to the left 
         if (matched== False): 
          right = right-1 
          left = left-1 


        previous_column = running_height.pop() 
        num_columns = previous_column[2] 
        if (len(running_height) > 0): 
         running_height[-1][1] += running_height[-1][0] * num_columns 
         running_height[-1][2] += num_columns 

      if (matched == False): 
       # this is either the left column, or we don't match to the column to the left, so reset 
       running_height = [[new_array[i][j],new_array[i][j],1]] 
       if (running_height[-1][1] > max_area): 
        max_area = running_height[-1][1] 
        top = i 
        right = j 
        bottom = i + running_height[-1][0]-1 
        left = j - running_height[-1][2]+1 


    max_array = [] 
    for i in range(top,bottom+1): 
     max_array.append(array[i][left:right+1]) 


    return max_array 



numbers = [[6,4,1,9],[5,2,2,7],[2,2,2,1],[2,3,1,5]] 

for row in numbers: 
    print row 

print 
print 

max_array = max_area_subarray(numbers)  


max_area = len(max_array) * len(max_array[0]) 
print 'max area is ',max_area 
print 
for row in max_array: 
    print row 
संबंधित मुद्दे