Cod sursa(job #2192813)

Utilizator georgeromanGeorge Roman georgeroman Data 7 aprilie 2018 13:19:52
Problema Jocul Flip Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.16 kb
#include <fstream>
#include <vector>

long flipRow(std::vector<std::vector<int>>& table, unsigned row) {
  long oldSum = 0, newSum = 0;
  for (unsigned j = 0; j < table[row].size(); j++) {
    oldSum += table[row][j];
    table[row][j] *= -1;
    newSum += table[row][j];
  }
  return newSum - oldSum;
}

long flipCol(std::vector<std::vector<int>>& table, unsigned col) {
  long oldSum = 0, newSum = 0;
  for (unsigned i = 0; i < table.size(); i++) {
    oldSum += table[i][col];
    table[i][col] *= -1;
    newSum += table[i][col];
  }
  return newSum - oldSum;
}

bool isValid(std::vector<std::vector<int>>& table, std::vector<int>& stack, unsigned size) {
  if (stack.size() >= size) return false;
  if (stack[stack.size() - 1] >= size) return false;
  if (stack[stack.size() - 1] < 0) return false;
  if (stack.size() >= 2 && stack[stack.size() - 1] <= stack[stack.size() - 2]) return false;
  if (stack.size() > size / 2) return false;
  return true;
}

int main() {
  std::ifstream in("flip.in");
  std::ofstream out("flip.out");

  int n, m;
  in >> n >> m;

  std::vector<std::vector<int>> table = std::vector<std::vector<int>>();
  table.reserve(n);
  for (int i = 0; i < n; i++) {
    table.push_back(std::vector<int>());
    table[i].reserve(m);
  }

  long currentSum = 0;
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < m; j++) {
      int num;
      in >> num;
      table[i].push_back(num);
      currentSum += num;
    }
  }
  long maxSum = currentSum;

  std::vector<int> flippedCols = std::vector<int>();
  flippedCols.reserve(m);
  for (int j = 0; j < m; j++) {
    long diff = flipCol(table, j);
    if (diff > 0) {
      currentSum += diff;
      flippedCols.push_back(j);
    } else {
      flipCol(table, j);
    }
  }
  if (currentSum > maxSum) {
    maxSum = currentSum;
  }
  for (unsigned i = 0; i < flippedCols.size(); i++) {
    currentSum += flipCol(table, flippedCols[i]);
  }
  flippedCols.clear();

  std::vector<int> rowStack = std::vector<int>();
  rowStack.push_back(-1);
  while (rowStack.size() != 0) {
    bool found = false;
    if (rowStack[rowStack.size() - 1] >= 0) {
      currentSum += flipRow(table, rowStack[rowStack.size() - 1]);
    }
    while (rowStack[rowStack.size() - 1] < n) {
      rowStack[rowStack.size() - 1]++;
      if (isValid(table, rowStack, n)) {
        found = true;
        break;
      }
    }
    if (found) {
      currentSum += flipRow(table, rowStack[rowStack.size() - 1]);
      if (currentSum > maxSum) {
        maxSum = currentSum;
      }

      for (int j = 0; j < m; j++) {
        long diff = flipCol(table, j);
        if (diff > 0) {
          currentSum += diff;
          flippedCols.push_back(j);
        } else {
          flipCol(table, j);
        }
      }
      if (currentSum > maxSum) {
        maxSum = currentSum;
      }
      for (unsigned i = 0; i < flippedCols.size(); i++) {
        currentSum += flipCol(table, flippedCols[i]);
      }
      flippedCols.clear();

      rowStack.push_back(-1);
    } else {
      if (rowStack[rowStack.size() - 1] > 0 && rowStack[rowStack.size() - 1] < n) {
        flipRow(table, rowStack[rowStack.size() - 1]);
      }
      rowStack.pop_back();
    }
  }

  out << maxSum;

  return 0;
}