代码拉取完成,页面将自动刷新
#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;
}