!-- Loading 底层遮罩 -->

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;
}
 

 

posted @ 2022-03-30 20:10  Thinker-X  阅读(32)  评论(0)    收藏  举报