Advertisement
Guest User

Finding the largest square submatrix with identical rows

a guest
Mar 20th, 2015
385
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.48 KB | None | 0 0
  1. #include <iostream>
  2. #include <algorithm>
  3. #include <vector>
  4. #include <string>
  5. //#include "sequence_lister.h"
  6.  
  7. using namespace std;
  8.  
  9. int n, m;       // n = number of rows, m = number of cols
  10. vector<vector<int> > x;     // x[i][j] = number at row i+1, col j+1
  11. int biggest = 0;
  12. unsigned long long nSearchNodes = 0;
  13. unsigned long long nDominancePrunings = 0;
  14. unsigned long long nFathomed = 0;
  15. unsigned long long nFathomedByRowCount = 0;
  16.  
  17. // The partial solution so far is the set of rows in rows.
  18. // Every column in cols is identical across these rows.
  19. // The first row to consider adding next is nextRow.
  20. // We can reorder rows freely in x[][] from nextRow on down.
  21. // E.g. we can pick any row at or below nextRow and swap it with
  22. // the row at nextRow.
  23. void solve(vector<int>& rows, int nextRow, vector<int>& cols) {
  24.     //cerr << "solve(rows=" << list_sequence(rows) << ", nextRow=" << nextRow << ", cols=" << list_sequence(cols) << ") called.\n";     //DEBUG
  25.     ++nSearchNodes;
  26.     //if (cols.empty()) {
  27.     //if (cols.size() < biggest) {
  28.     if (cols.size() <= biggest) {
  29.         // We've run out of options.
  30.         if (!cols.empty()) {
  31.             ++nFathomed;
  32.         }
  33.        
  34.         return;
  35.     }
  36.    
  37.     if (nextRow == n) {
  38.         // No more rows to try adding.
  39.         return;
  40.     }
  41.    
  42.     // First look for the best row to branch on.  A good approximation is
  43.     // to pick the one that results in the fewest remaining columns.
  44.     // But we override this with a (probably very strong) domination rule:
  45.     // Whenever we can add a row without shrinking cols at all, we can
  46.     // immediately do it, and we never have to consider not adding it.
  47.     //HACK: This will wind up just picking the 1st row on the very first call,
  48.     // but that's not so bad.
  49.     int iBestRow;
  50.     bool canForceIn = false;
  51.     int nBestSameCols = INT_MAX;
  52.     int nPotentialRows = 0;
  53.     for (int i = nextRow; i < n; ++i) {
  54.         int nSameCols = 0;
  55.         for (int ic = 0; ic < cols.size(); ++ic) {
  56.             if (rows.empty() || x[i][cols[ic]] == x[rows.front()][cols[ic]]) {
  57.                 ++nSameCols;
  58.             }
  59.         }
  60.        
  61.         if (!rows.empty() && nSameCols == cols.size()) {
  62.             // We can stop right here, we have a winner ;)
  63.             iBestRow = i;
  64.             canForceIn = true;
  65.             break;
  66.         }
  67.        
  68.         if (nSameCols < nBestSameCols) {
  69.             iBestRow = i;
  70.             nBestSameCols = nSameCols;
  71.         }
  72.        
  73.         if (nSameCols >= biggest) {
  74.             ++nPotentialRows;
  75.         }
  76.     }
  77.    
  78.     if (!canForceIn && rows.size() + nPotentialRows <= biggest) {
  79.         // Even if all the rows that match at least biggest columns were to be compatible
  80.         // (i.e. match on the same columns), there still wouldn't be enough rows to
  81.         // make a difference.
  82.         ++nFathomedByRowCount;
  83.         return;
  84.     }
  85.    
  86.     // Rearrange x[][] so the chosen row comes next.
  87.     swap(x[nextRow], x[iBestRow]);
  88.    
  89.     // Try forcing this row in.
  90.     vector<int> newCols;
  91.    
  92.     if (canForceIn || !rows.empty()) {
  93.         // Form the reduced set of columns.
  94.         for (int i = 0; i < cols.size(); ++i) {
  95.             if (x[nextRow][cols[i]] == x[rows.front()][cols[i]]) {
  96.                 newCols.push_back(i);
  97.             }
  98.         }
  99.     } else {
  100.         // Otherwise just leave the set of columns at the complete set.
  101.         //TODO: Could maybe speed up by avoiding the copy somehow.
  102.         newCols = cols;
  103.     }
  104.    
  105.     rows.push_back(nextRow);
  106.     //if (rows.size() > biggest && newCols.size() > biggest)
  107.     if (rows.size() > biggest && newCols.size() >= biggest) {       // Let's also report when we get a taller solution of the same width
  108.         //biggest = newCols.size();
  109.         biggest = min(newCols.size(), rows.size());
  110.         cerr << "New solution of size " << biggest << " found with width " << newCols.size() << ", height " << rows.size() << "!\n";
  111.     }
  112.    
  113.     solve(rows, nextRow + 1, newCols);
  114.    
  115.     // Try forcing this row out -- but only if we have to!
  116.     rows.pop_back();
  117.     if (!canForceIn) {
  118.         solve(rows, nextRow + 1, cols);
  119.     } else {
  120.         ++nDominancePrunings;
  121.     }
  122. }
  123.  
  124. int main(int argc, char **argv) {
  125.     cin >> n >> m;
  126.    
  127.     cerr << "About to read in a " << n << '*' << m << " matrix...\n";
  128.    
  129.     x.resize(n, vector<int>(m, 0));
  130.     for (int i = 0; i < n; ++i) {
  131.         for (int j = 0; j < m; ++j) {
  132.             cin >> x[i][j];
  133.         }
  134.     }
  135.    
  136.     cerr << "Read in a " << n << '*' << m << " matrix.\n";
  137.    
  138.     vector<int> rows;
  139.     vector<int> cols;
  140.     for (int i = 0; i < m; ++i) {
  141.         cols.push_back(i);
  142.     }
  143.    
  144.     solve(rows, 0, cols);
  145.    
  146.     cerr << "Finished.  Biggest solution has width " << biggest << " (and at least the same height).\n";
  147.     cerr << nSearchNodes << " search nodes evaluated; " << nDominancePrunings << " nodes could be pruned due to dominance; " << nFathomed << " fathomed via B&B columns; " << nFathomedByRowCount << " fathomed via B&B rows.\n";
  148.     return 0;
  149. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement