题解HNOI2004敲砖块

Posted Twilight_Sx

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了题解HNOI2004敲砖块相关的知识,希望对你有一定的参考价值。

题目传送门:洛谷1437

 

决定要养成随手记录做过的题目的好习惯呀~

这道题目乍看起来和数字三角形有一点像,但是仔细分析就会发现,因为选定一个数所需要的条件和另一个数所需要的条件会有重复的部分,所以状态不好转移,也会产生后效性。

但是,通过将所有的砖块左移,我们可以发现(i, j)砖块所需要的条件就是(i-1, j) (i-1, j+1)这两块砖均被敲掉。

所以dp方程顺理成章:i,j,k分别表示从第i列j行开始算起,取k个数所能获得的最大价值和。

dp[i][j][s] = max(dp[i+1][s][k-j] +sum[第i列前j个数之和])(s>=j+1,<=该行最大数目)

 

#include <bits/stdc++.h>
using namespace std;
#define maxn 55
#define maxm 1500
int n, m, ans, sum[maxn][maxn], dp[maxn][maxn][maxm];
int read()
{
    int x = 0;
    char c;
    c = getchar();
    while(c < 0 || c > 9) c = getchar();
    while(c >= 0 && c <= 9) x = x * 10 + c - 0, c = getchar();
    return x;
}

int main()
{
    n = read(), m = read();
    for(int i = 1; i <= n; i ++)
        for(int j = 1; j <= n - i + 1; j ++)
            sum[j][i] += read() + sum[j][i - 1];
    for(int i = n; i >= 1; i --)
    {
        int len = n - i + 1;
        for(int j = 0; j <= len; j ++)
            for(int s = m; s >= max(0, 2 * j - 1); s --)
                for(int k = j - 1; k <= len - 1; k ++)
                {
                    dp[i][j][s] = max(dp[i + 1][k][s - j] + sum[i][j], dp[i][j][s]);
                    ans = max(ans, dp[i][j][s]);
                }
    }
    printf("%d\n", ans);
    return 0;
}

 

以上是关于题解HNOI2004敲砖块的主要内容,如果未能解决你的问题,请参考以下文章

@@P1437 [HNOI2004]敲砖块

P1437 [HNOI2004]敲砖块(dp)

luogu P1437 [HNOI2004]敲砖块

HNOI2004 打砖块

题解 bzoj1207: [HNOI2004]打鼹鼠 (动态规划)

BZOJ1208: [HNOI2004]宠物收养所