題目鏈接:https://www.acwing.com/problem/content/1029/
解題思路:
首先,這道題目我們基本可以確定是一道DP的題目,但是問題的關鍵在於怎樣去DP;一開始我發現直接先後求兩次最大數值,但是發現這樣是錯誤的,然後,我就沒有想出來先後分別兩次跑路徑的解法;但是後面我發現了一個性質:兩條路徑的起點和終點是一樣的,所以這裏有一個性質,當我們走到(n, n)的時候,兩條路徑的列 + 行 這個和一定是相等的,然後對於這兩條路勁來說,誰先走是沒有影響的,所以我們可以假設兩條路徑同時走,這樣就保證了 行 + 列 的和是一樣的;由於有兩條路徑所以初步的時候可以開闢一個思維舉證:
f[i1, j1, i2, j2]後面發現 i1 + j1 == i2 + j2,所以可以優化爲 f[k, i1, i2]
但是這裏還存在一個問題,就是這兩條路徑中間可能出現重合的情況,由於我們是dp過來的,所以我們只需要考慮當前情況,這兩條路徑是否重合,所以我們可以判斷:i1 == i2? 來判斷此時是否重合。
AC代碼:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = 15;
int n;
int f[maxn * 2][maxn][maxn];
int m[maxn][maxn];
int main(void) {
// freopen("in.txt", "r", stdin);
scanf("%d", &n);
int x, y, z;
while(scanf("%d%d%d", &x, &y, &z) && (x || y || z)) m[x][y] = z;
for(int k = 2; k <= 2 * n; k ++)
for(int i1 = 1; i1 <= n; i1 ++)
for(int i2 = 1; i2 <= n; i2 ++) {
int j1 = k - i1, j2 = k - i2;
if(j1 >= 1 && j1 <= n && j2 >= 1 && j2 <= n) {
int &x = f[k][i1][i2];
int t = m[i1][j1];
if(i1 != i2) t += m[i2][j2];
x = max(x, f[k - 1][i1][i2] + t);
x = max(x, f[k - 1][i1][i2 - 1] + t);
x = max(x, f[k- 1][i1- 1][i2] + t);
x = max(x, f[k - 1][i1 - 1][i2 - 1] + t);
}
}
printf("%d\n", f[n * 2][n][n]);
return 0;
}