1 Star 0 Fork 0

丑芹 / mynotes

 / 详情

game.cc

待办的
拥有者
创建于  
2015-05-20 12:49
#include <iostream>
#include <stdexcept>
#include <cstdio>
#include <queue>

using namespace std;

// Compute score based on neighbor score and current value
int compute_score(int neighbor_score, int current_value) {
  if (neighbor_score == -1 || current_value == -1) {
    return -1;
  } else {
    return neighbor_score + current_value;
  }
}

/**
 * Compute max score for the first column.
 * Max score of a cell can come from three directions: up and down.
 * If the max score comes from the up cell, the max score of the up cell
 * must come from the up cell.
 * If the max score comes from the down cell, the max score of the down cell
 * must come from the down cell.
 * So we can compute the max score in two directions: buttom up and top down.
 */
void init_max_score(int* cur_max, int** values, int n) {
  // compute max values top down
  int* top_down =  new int[n];
  top_down[0] = values[0][0];
  for (int i = 1; i < n; ++i) {
    top_down[i] = max(compute_score(top_down[i-1], values[i][0]), values[i][0]);
  }

  // compute max values buttom up
  int* buttom_up =  new int[n];
  buttom_up[n-1] = values[n-1][0];
  for (int i = n-2; i >= 0; --i) {
    buttom_up[i] = max(compute_score(buttom_up[i+1], values[i][0]), values[i][0]);
  }

  // the max score of a cell the max of the two scores computed in two directions
  for (int i = 0; i < n; ++i) {
    cur_max[i] = max(top_down[i], buttom_up[i]);
  }
  delete [] top_down;
  delete [] buttom_up;
}

/**
 * Compute max score for column j based on:
 * \param cur_max: max score for column j-1
 * \param values: value for each cell
 * \param connected_top: connected status for the top cells
 * \param connected_buttom: connected status for the buttom cells
 * \param n: number of rows
 * \param j: column number to compute
 *
 * Max score of a cell can come from three directions: left, up and down.
 * If the max score comes from the up cell, the max score of the up cell
 * must come from the left cell or the up cell.
 * If the max score comes from the down cell, the max score of the down cell
 * must come from the left cell or the down cell.
 * So we can compute the max score in two directions: buttom up and top down.
 */
void compute_max_score(int* cur_max, int** values, bool* connected_top,
                bool* connected_buttom, int n, int j) {
  // compute max values top down
  int* top_down =  new int[n];
  // the max score for the top cell comes from the left cell
  // or the buttom cell(if the buttom cell is connected)
  if (connected_buttom[j]) {
    top_down[0] = max(compute_score(cur_max[0], values[0][j]), values[0][j]);
  } else {
    top_down[0] = compute_score(cur_max[0], values[0][j]);
  }
  for (int i = 1; i < n; ++i) {
    top_down[i] = max(compute_score(top_down[i-1], values[i][j]),
                      compute_score(cur_max[i], values[i][j]));
  }

  // compute max values buttom up
  int* buttom_up =  new int[n];
  // the max score for the buttom cell can come from the left cell and
  // the top cell(if the top cell is connected)
  if (connected_top[j]) {
    buttom_up[n-1] = max(compute_score(cur_max[n-1], values[n-1][j]), values[n-1][j]);
  } else {
    buttom_up[n-1] = compute_score(cur_max[n-1], values[n-1][j]);
  }
  for (int i = n-2; i >= 0; --i) {
    buttom_up[i] = max(compute_score(buttom_up[i+1], values[i][j]),
                       compute_score(cur_max[i], values[i][j]));
  }

  // the max score of a cell the max of the two scores computed in two directions
  for (int i = 0; i < n; ++i) {
    cur_max[i] = max(top_down[i], buttom_up[i]);
  }

  delete [] top_down;
  delete [] buttom_up;
}

// Get connect status of the cell in the top row or the buttom row.
// A cell is connected if it can be reached in this game.
// Use a bfs algorithm here.
void get_connected(bool* connected_top, bool* connected_buttom, int ** values, int n, int m) {
  bool** connected_all = new bool*[n];
  for (int i = 0; i < n; ++i) {
    connected_all[i] = new bool[m];
    for (int j = 0; j < m; ++j) {
      connected_all[i][j] = false;
    }
  }

  queue<pair<int, int> > connected_elems;
  // enqueue connected elements for the first column
  for (int i = 0; i < n; ++i) {
    if (values[i][0] >= 0) {
      connected_all[i][0] = true;
      connected_elems.push(make_pair(i, 0));
    }
  }

  // get elements from queue, and update connect status
  while(!connected_elems.empty()) {
    pair<int, int> ij = connected_elems.front();
    connected_elems.pop();
    int i = ij.first;
    int j = ij.second;

    // check the up element
    if (i == 0 && !connected_all[n-1][j] && values[n-1][j] >= 0) {
      connected_all[n-1][j] = true;
      connected_elems.push(make_pair(n-1, j));
    } else if (i > 0 && !connected_all[i-1][j] && values[i-1][j] >= 0) {
      connected_all[i-1][j] = true;
      connected_elems.push(make_pair(i-1, j));
    }

    // check the down element
    if (i == (n-1) && !connected_all[0][j] && values[0][j] >= 0) {
      connected_all[0][j] = true;
      connected_elems.push(make_pair(0, j));
    } else if (i < (n-1) && !connected_all[i+1][j] && values[i+1][j] >= 0) {
      connected_all[i+1][j] = true;
      connected_elems.push(make_pair(i+1, j));
    }

    // check the right element
    if (j < (m-1) && !connected_all[i][j+1] && values[i][j+1] >= 0) {
      connected_all[i][j+1] = true;
      connected_elems.push(make_pair(i, j+1));
    }
  }

  for (int j = 0; j < m; ++j) {
    connected_top[j] = connected_all[0][j];
  }
  for (int j = 0; j < m; ++j) {
    connected_buttom[j] = connected_all[n-1][j];
  }

  for (int i = 0; i < n; ++i) {
    delete [] connected_all[i];
  }
  delete [] connected_all;
}

int main() {
  // get input n and m
  int n, m;
  cin >> n >> m;

  // if m is not valid, throw exception()
  if (m <= 0) {
    throw invalid_argument("invalid m");
  }

  // get input values
  int** values = new int*[n];
  for (int i = 0; i < n; ++i) {
    values[i] = new int[m];
    for (int j = 0; j < m; ++j) {
      cin >> values[i][j];
    }
  }

  // get connected status
  bool* connected_top = new bool[m];
  bool* connected_buttom = new bool[m];
  get_connected(connected_top, connected_buttom, values, n, m);

  // compute max scores column by column
  int* cur_max = new int[n];
  init_max_score(cur_max, values, n);
  for (int j = 1; j < m; ++j) {
    compute_max_score(cur_max, values, connected_top, connected_buttom, n, j);
  }

  // get results from the last column
  int max = -1;
  for (int i = 0; i < n; ++i) {
    if (cur_max[i] > max) {
      max = cur_max[i];
    }
  }
  cout << max << endl;

  // delete arrays
  delete [] connected_top;
  delete [] connected_buttom;
  delete [] cur_max;
  for (int i = 0; i < n; ++i) {
    delete [] values[i];
  }
  delete [] values;

  return 0;
}

评论 (0)

登录 后才可以发表评论

状态
负责人
里程碑
Pull Requests
关联的 Pull Requests 被合并后可能会关闭此 issue
分支
开始日期   -   截止日期
-
置顶选项
优先级
参与者(1)
1
https://gitee.com/chouqin/mynotes.git
git@gitee.com:chouqin/mynotes.git
chouqin
mynotes
mynotes

搜索帮助