有n*n个格子,每个格子里有正数或者0,从最左上角往最右下角走,只能向下和向右,一共走两次(即从左上角走到右下角走两趟),把所有经过的格子的数加起来,求最大值SUM,且两次如果经过同一个格子,则最后总和SUM中该格子的计数只加一次。
#define N 6
//使用滚动数组,因为每次状态计算只要用到前一次的记录即可
int dp[2][N][N] = { 0 };
/*坐标是否满足要求*/
bool isVaild(int step, int x1, int x2, int n) {
//step-x=y
if ((x1 >= 0) && (x1 < n) && (step - x1 >= 0) && (step - x1 < n)
&& (x2 >= 0) && (x2 < n) && (step - x2 >= 0) && (step - x2 < n)) {
return true;
}
return false;
}
int getNum(int step, int x1, int x2, int n) {
return isVaild(step, x1, x2, n) ? dp[step % 2][x1][x2] : 0;
}
int cellMax(int matrix[N][N], int n) {
int endStep = 2 * n - 2; //走到末尾需要步数
dp[0][0][0] = matrix[0][0];
for (int step = 1; step <= endStep; ++step) {
int curIndex = step % 2;
for (int i = 0; i < n; ++i) {
for (int j = i; j < n; ++j) { //j>=i保证不交叉
if (!isVaild(step, i, j, n)) {
continue;
}
/*不管格子是否一致都有x1,x2相对于格子上上, 左左, 上左,由于x1<=x2,所以左上不一定成立*/
dp[curIndex][i][j] = max(dp[curIndex][i][j],
getNum(step - 1, i, j, n));
dp[curIndex][i][j] = max(dp[curIndex][i][j],
getNum(step - 1, i - 1, j - 1, n));
dp[curIndex][i][j] = max(dp[curIndex][i][j],
getNum(step - 1, i - 1, j, n));
if (i != j) { //当前状态不同格子
dp[curIndex][i][j] = max(dp[curIndex][i][j],
getNum(step - 1, i, j - 1, n));
//加2次
dp[curIndex][i][j] += matrix[i][step - i]
+ matrix[j][step - j];
} else {
/* i==j
* matrix[i][step-i]只加一次
* 并且i<=j
* 则 i>j-1 不计算*/
dp[curIndex][i][j] += matrix[i][step - i];
}
}
}
// cout << step << endl;
// printMatrix(dp, N);
}
return dp[endStep % 2][n - 1][n - 1];
}