思路
f[i,j]表示从(1,1)走到(i,j)所有可能路径的集合 所获取的最大值
f[i1,j1,i2,j2]为2次走的和的最大值。
i1 + j1 = i2 + j2 //只有相等时,才有可能走到同一个位置,也就是第一个走的人获得。
令i1 + j1 = i2 + j2 = k,简化为f[k,i1,i2]:从(1,1)走到(i1,k-i1)和(i2,k-i2)
状态划分为:最后一步:
下 下 (1,1) -> (i1-1,j1) -> (i1,j1) (1,1) -> (i2-1,j2) -> (i2,j2)
f[k-1][i1-1][i2-1] -> f[k][i1][i2]
下 右 (1,1) -> (i1-1,j1) -> (i1,j1) (1,1) -> (i2,j2-1) -> (i2,j2)
f[k-1][i1-1][i2] -> f[k][i1][i2]
右 下 ……
右 右 ……
const N = 15;
let f = [];
for (let i = 0; i < 2 * N; i++) f[i] = new Array(N);
for (let i = 0; i < 2 * N; i++) {
for (let j = 0; j < N; j++) {
f[i][j] = new Int32Array(N);
}
}
let g = [];
for (let i = 0; i < N; i++) g[i] = new Int32Array(N);
let n = 0;
let flag = true;
let buf = '';
process.stdin.on('readable', function () {
let chunk = process.stdin.read();
if (chunk) buf += chunk.toString();
});
let getInputNums = line => line.split(' ').filter(s => s !== '').map(x => parseInt(x));
let getInputStr = line => line.split(' ').filter(s => s !== '');
process.stdin.on('end', function () {
buf.split('\n').forEach(function (line, lineIdx) {
if (lineIdx === 0) {
n = getInputNums(line)[0];
} else if (flag) {
let arr = getInputNums(line);
let x = arr[0],
y = arr[1],
z = arr[2];
if (x === 0 && y === 0 && z === 0) flag = false;
g[x][y] = z;
if (!flag) {
for (let k = 2; k <= 2 * n; k++) { // k = i1 + j1
for (let i1 = 1; i1 <= n; i1++) {
for (let i2 = 1; i2 <= n; i2++) {
let j1 = k - i1,
j2 = k - i2;
if (j1 >= 1 && j1 <= n && j2 >= 1 && j2 <= n) {
let t = g[i1][j11];
if (i1 !== i2) t += g[i2][j2];
f[k][i1][i2] = Math.max(f[k][i1][i2], f[k - 1][i1 - 1][i2 - 1] + t);
f[k][i1][i2] = Math.max(f[k][i1][i2], f[k - 1][i1 - 1][i2] + t);
f[k][i1][i2] = Math.max(f[k][i1][i2], f[k - 1][i1][i2 - 1] + t);
f[k][i1][i2] = Math.max(f[k][i1][i2], f[k - 1][i1][i2] + t);
}
}
}
}
console.log(f[2 * n][n][n]);
}
}
});
});