P1437 敲砖块 题解

题意

在一个凹槽中放置了 \(n\) 层砖块、最上面的一层有 \(n\) 块砖,从上到下每层依次减少一块砖。每块砖都有一个分值,敲掉这块砖就能得到相应的分值,如下图所示:

14 15  4  3  23
33 33 76  2
2  13 11
22 23
31

如果你想敲掉第 \(i\) 层的第 \(j\) 块砖的话,若 \(i = 1\),你可以直接敲掉它;若 \(i>1\),则你必须先敲掉第 \(i−1\) 层的第 \(j\) 和第 \(j + 1\) 块砖。你现在可以敲掉最多 \(m\) 块砖,求得分最多能有多少。

\(\tt{Solution}\)

观察题目性质,发现每一列敲掉的砖块都是自上而下的连续的一段,而倒三角不便于转移,考虑转化一下。
将给定的倒三角逆时针旋转 \(90°\) 变为正三角,那么现在对转化后的进行 DP 转移。

考虑对于 \((i,j)\),它被敲掉的充要条件的是 \((i,j - 1)\)\((i - 1,j - 1)\) 都被敲掉。那么可以定义 \(f_{i,j,k}\) 表示转移到 \((i,j)\) 敲掉了 \(k\) 个砖块的最大价值总和。转化后可以前缀和预处理每一行的贡献,然后就做完了。

#include <bits/stdc++.h>

#define int long long
#define ll long long
#define ull unsigned long long
#define db double
#define ld long double
#define rep(i,l,r) for (int i = (int)(l); i <= (int)(r); ++ i )
#define rep1(i,l,r) for (int i = (int)(l); i >= (int)(r); -- i )
#define il inline
#define fst first
#define snd second
#define ptc putchar
#define Yes ptc('Y'),ptc('e'),ptc('s'),puts("")
#define No ptc('N'),ptc('o'),puts("")
#define YES ptc('Y'),ptc('E'),ptc('S'),puts("")
#define NO ptc('N'),ptc('O'),puts("")
#define pb emplace_back
#define sz(x) (int)(x.size())
#define all(x) x.begin(),x.end()
#define get(x) ((x - 1) / len + 1)
#define debug() puts("------------")

using namespace std;
typedef pair<int,int> PII;
typedef pair<int,PII> PIII;
typedef pair<ll,ll> PLL;
namespace szhqwq {
    template<class T> il void read(T &x) {
        x = 0; T f = 1; char ch = getchar();
        while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); }
        while (ch >= '0' && ch <= '9') { x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar(); }
        x *= f;
    }
    template<class T,class... Args> il void read(T &x,Args &...x_) { read(x); read(x_...); }
    template<class T> il void print(T x) {
        if (x < 0) ptc('-'), x = -x; 
        if (x > 9) print(x / 10); ptc(x % 10 + '0');
    }
    template<class T,class T_> il void write(T x,T_ ch) { print(x); ptc(ch); }
    template<class T,class T_> il void chmax(T &x,T_ y) { x = max(x,y); }
    template<class T,class T_> il void chmin(T &x,T_ y) { x = min(x,y); }
    template<class T,class T_,class T__> il T qmi(T a,T_ b,T__ p) {
        T res = 1; while (b) {
            if (b & 1) res = res * a % p;
            a = a * a % p; b >>= 1;
        } return res;
    }
    template<class T> il T gcd(T a,T b) { if (!b) return a; return gcd(b,a % b); }
    template<class T,class T_> il void exgcd(T a, T b, T_ &x, T_ &y) {
        if (b == 0) { x = 1; y = 0; return; }
        exgcd(b,a % b,y,x); y -= a / b * x; return ;
    }
    template<class T,class T_> il T getinv(T x,T_ p) { T inv,y; exgcd(x,(T)p,inv,y); inv = (inv + p) % p; return inv; }
} using namespace szhqwq;
const int N = 60,inf = 1e9,mod = 998244353;
const ull base = 131,base_ = 233;
const ll inff = 1e18;
int n,m,a[N][N],f[N][N][N * N],s[N][N];

il void solve() {
    //------------code------------
    read(n,m);
    rep(j,1,n) rep1(i,n,j) read(a[i][j]);
    rep(i,1,n) rep(j,1,i) s[i][j] = s[i][j - 1] + a[i][j];
    f[1][1][1] = a[1][1]; f[1][0][0] = 0;
    rep(i,2,n)
        rep(k,0,m) {
            rep(lst,0,min(i - 1,k))
                rep(j,0,min(lst + 1,k - lst))
                    chmax(f[i][j][k],f[i - 1][lst][k - j] + s[i][j]);
        }
    ll ans = 0;
    rep(i,0,n) chmax(ans,f[n][i][m]);
    write(ans,'\n');
    return ;
}

il void init() {
    return ;
}

signed main() {
    // init();
    int _ = 1;
    // read(_);
    while (_ -- ) solve();
    return 0;
}
posted @ 2024-11-15 19:14  songszh  阅读(4)  评论(0编辑  收藏  举报