1. 程式人生 > 其它 >P1004 方格取數

P1004 方格取數

傳送門

由於兩次動規無法保證最優解,需要雙線並行,定義狀態 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; }