洛谷P1437 敲砖块

题目大意:给定n*n的上半个矩阵,每一点表示一个砖块。有敲掉该块砖能得到的相应的分值。对于(i,j)的砖块,若i==1,则可以直接敲掉;若i>1,则必须先敲掉(i-1,j)和(i-1,j+1);现在最多可以敲掉m块砖,求最大得分

sum[i][j]:第j列的前缀和
dp[i][j][k]:敲(j, i)的砖块,敲了k次的最大分数
敲掉i+1列的砖和1~i列的砖毛有关系,没有后效性,可以dp
状态转移:考虑状态(j,i)的砖,上一步状态有{(j-1,i+1),(j,i+1),…,(n-i,i+1)},则在其中去一个最大值即可。
状态转移方程:dp[i][j][k]=max(dp[i+1][p][k-j]+sum[j][i]);(j-1<=p<=n-i)

#include <cstdio>
#include <algorithm>
#include <cstring>

using namespace std;

int n, m;
int sum[55][55], dp[55][55][1510];

int main()
{
    scanf("%d %d", &n, &m);
    memset(sum, 0, sizeof(sum));
    for(int i = 1; i <= n; ++i)
        for(int j = 1; j <= n-i+1; ++j)
        {
            scanf("%d", &sum[i][j]);
            sum[i][j]+=sum[i-1][j];
        }
    memset(dp, -1, sizeof(dp));
    dp[n+1][0][0] = 0;
    for(int i = n; i>=1; --i)
        for(int j = 0; j<=n-i+1; ++j)
            for(int k = j; k<=m; ++k)//最少取j
                for(int p = max(j-1,0); p<=n-i; ++p)
                    if(dp[i+1][p][k-j]>=0)//如果更新过
                        dp[i][j][k] = max(dp[i][j][k],dp[i+1][p][k-j]+sum[j][i]);
    int ans = 0;
    for(int i = 1; i <= n; ++i)
        for(int j = 1; j <= n-i+1; ++j)
            ans = max(ans, dp[i][j][m]);
    printf("%d\n", ans);
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值