P1004 方格取數
阿新 • • 發佈:2022-03-30
由於兩次動規無法保證最優解,需要雙線並行,定義狀態 f(i,j,k,l)為兩條路徑的位置,有s=i+j=k+l,從而得出優化的方式,狀態 f(s,i,k)表示走了s步第一路徑到 i 行(s-i 列),第二路徑到 k 行(s-k列)。這樣的狀態可以由四個s-1步方位進行轉移。處理格子貢獻時,若 i == k 則路徑重疊,只加一次。
#include<iostream> #define maxn 207 using namespace std; int dp[maxn << 1][maxn][maxn], g[maxn][maxn], n; int main(void) { int xpos = 0, ypos = 0; cin >> n; while (cin >> xpos >> ypos) { cin >> g[xpos][ypos]; if (!xpos && !ypos) break; } for (int s = 2; s <= n << 1; s++) { for (int i = max(s - n, 1); i <= min(s - 1, n); i++) {for (int k = max(s - n, 1); k <= min(s - 1, n); k++) { dp[s][i][k] = dp[s - 1][i][k]; dp[s][i][k] = max(dp[s][i][k], dp[s - 1][i - 1][k - 1]); dp[s][i][k] = max(dp[s][i][k], dp[s - 1][i][k - 1]); dp[s][i][k] = max(dp[s][i][k], dp[s - 1][i - 1][k]); if (i != k) dp[s][i][k] += g[i][s - i] + g[k][s - k]; else dp[s][i][k] += g[i][s - i]; } } } cout << dp[n << 1][n][n]; return 0; }