码迷,mamicode.com
首页 > 其他好文 > 详细

【题解】HNOI2004敲砖块

时间:2018-02-02 23:21:31      阅读:196      评论:0      收藏:0      [点我收藏+]

标签:www   tchar   name   分析   ret   数字   etc   传送门   通过   

题目传送门:洛谷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敲砖块

标签:www   tchar   name   分析   ret   数字   etc   传送门   通过   

原文地址:https://www.cnblogs.com/twilight-sx/p/8407172.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!