Loading

【题解】P1437 [HNOI2004] 敲砖块

题意

P1437 [HNOI2004] 敲砖块

给定一个凹槽 \(a\),第 \(i\) 行(列)有 \(n - i + 1\) 个值,第 \(i\) 行第 \(j\) 列的值为 \(a_{i, j}\)。限制取 \(a_{i, j}\) 前必须取 \(a_{i - 1, j}\)\(a_{i - 1, j + 1}\)。在至多取 \(m\) 个值的情况下,求取出的值的和的最大值。

\(1 \leq n \leq 50, 1 \leq m \leq \frac{n(n + 1)}{2}\)

思路

“二维xjbDP”(或 bdfs,即 Baidu-First Search)

贪心一类的乱搞显然难过,一眼 dp。

容易想到以行划分状态,但是第 \(i\) 行是否能取与第 \(i - 1\) 行的状态有关,即状态有后效性,所以是错的。

我们发现后效性与列有关,所以考虑以列划分状态。即令产生后效性的状态被预先确定好,使其不能影响当前状态。容易看到对于第 \(j\) 列,如果要取到第 \(i\) 行,则必须要取前 \(i - 1\) 行,并且第 \(j + 1\) 列至少要取到第 \(i - 1\) 行。

基于这种思路,令 \(dp[i][j][k]\) 表示取到第 \(i\) 列第 \(j\) 行,一共取 \(k\) 个值时的答案。根据上文,此时能转移过来的状态是 \([\ dp[i + 1][j - 1][k - j], dp[i + 1][n - (i + 1) + 1][k - j]\ ]\)。所以得到状态转移方程:

\(dp[i][j][k] = \max_{l = j - 1}^{n - (i + 1) + 1}(dp[i + 1][l][k - j]) + \sum\limits_{k = 1}^j a_{k, i}\)

朴素 dp 时间复杂度太高,考虑优化。

\(\sum\limits_{k = 1}^j a_{k, i}\) 可以前缀和预处理。\(\max_{l = j - 1}^{n - (i + 1) + 1}(dp[i + 1][l][k - j])\) 也可以后缀最大值预处理,所以时间复杂度优化成 \(O(n^2m)\)。容易发现第 \(i\) 行状态的转移只与第 \(i + 1\) 行的状态有关,因此可以滚动数组。

时间复杂度 \(O(n^2m)\),空间复杂度 \(O(nm)\)

代码

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int maxn = 55;
const int maxm = 1.3e3 + 5;

int n, m;
int a[maxn][maxn];
int dp[2][maxn][maxm];

int main()
{
    int ans = 0;
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n - i + 1; j++) scanf("%d", &a[i][j]);
    for (int i = n; i >= 1; i--)
    {
        int cur = i & 1, sum = 0;
        memset(dp[cur], 0, sizeof(dp[cur]));
        for (int j = 1; j <= n - i + 1; j++) sum += a[j][i];
        for (int j = n - i + 1; j >= 0; j--)
        {
            for (int k = max((j << 1) - 1, 0); k <= m; k++)
            {
                dp[cur][j][k] = dp[cur ^ 1][max(j - 1, 0)][k - j] + sum;
                ans = max(ans, dp[cur][j][k]);
                dp[cur][j][k] = max(dp[cur][j][k], dp[cur][j + 1][k]);
            }
            sum -= a[j][i];
        }
    }
    printf("%d\n", ans);
    return 0;
}
posted @ 2022-06-06 15:15  kymru  阅读(40)  评论(0编辑  收藏  举报