1. 程式人生 > >luogu P1437 [HNOI2004]敲磚塊

luogu P1437 [HNOI2004]敲磚塊

getchar logs == body return sin ble const 前綴

三角形向右對齊後
你想打掉一個磚塊,那麽你必須打掉右上方的三角形,前綴和維護
若是第i列若是k個,那麽它右邊的那一列至少選了k-1個
f[i][j][k] 表示從後向前選到第 i 列第j個一共打了k次的分數

// luogu-judger-enable-o2
#include<cstdio>
#include<cstring>
#include<algorithm>
using std::max;
const int maxn = 57;
#define INF 0x7fffffff
inline int read()
{
    int x=0,f=1;char c=getchar();
    while
(c<'0'||c>'9'){ if(c=='-')f=-1; c=getchar(); } while(c<='9'&&c>='0')x=x*10+c-'0',c=getchar(); return x*f; } int n,m; int g[maxn][maxn],s[maxn][maxn]; int f[maxn][maxn][2507]; int main() { n=read();m=read(); for(int i=1;i<=n;++i) for
(int j=1;j<=n-i+1;++j) g[i][j]=read(); for(int i=1;i<=n;++i) for(int j=1;j<=n-i+1;++j) s[i][j]=s[i][j-1]+g[j][i]; for(int i=1;i<=n+1;++i) for(int j=0;j<=n+1;++j) for(int k=0;k<=m;++k) f[i][j][k]=-INF; f[n+1
][0][0]=0; int ans=0; for(int i=n;i;--i) for(int j=0;j<=n-i+1;++j) for(int k=j;k<=m;++k) { for(int l=max(0,j-1);l<=n-i;++l) { if(f[i+1][l][k-j]!=-INF) f[i][j][k]=max(f[i][j][k],f[i+1][l][k-j]+s[i][j]); } ans=max(ans,f[i][j][k]); } printf("%d\n",ans); return 0; }

luogu P1437 [HNOI2004]敲磚塊