題目描述:
在一個凹槽中放置了 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 塊磚,求得分最多能有多少。
輸入輸出格式
輸入格式:
輸入文件的第一行爲兩個正整數 n 和m;接下來n 行,描述這n 層磚塊上的分值a[i][j],滿足
0≤a[i][j]≤100。
對於 100%的數據,滿足1≤n≤50,1≤m≤n*(n+1)/2;
輸出格式:
輸出文件僅一行爲一個正整數,表示被敲掉磚塊的最大價值總和。
輸入輸出樣例
輸入樣例#1:
4 5
2 2 3 4
8 2 7
2 3
49
輸出樣例#1:
19
題解:
首先將磚塊全部左對齊,變成一個直角三角形的模樣。
可以得出如下結論:
1、每一列必須敲到由上到下的若干磚塊。
2、如果某一列敲掉了k個磚塊,那麼其右邊的那一列至少敲掉了k-1個磚塊。
設
最終答案爲
代碼:
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
int f[56][56][506];
int a[56][56],ans=0;
int n,m;
int get()
{
int x=0,p=1;
char c;
c=getchar();
if (c==' ') return x*p;
while (c<'0'||c>'9') {if (c=='-') p=-1;c=getchar();}
while (c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();}
return x*p;
}
int main()
{
int i,j,k,v;
n=get();m=get();
for (i=1;i<=n;i++)
for (j=1;j<=n-i+1;j++)
{
a[i][j]=get();
// f[n-i+1][j].s=a[n-i+1][j];
// f[n-i+1][j].s=a[n-i+1][j];
}
memset(f,-127,sizeof(f));
f[n+1][0][0]=0;
for (i=n;i>=1;i--)
for (j=0;j<=n-i+1;j++)
for (k=j;k<=m;k++)
{
for (v=j-1;v<=n-i;v++)
if (f[i+1][v][k-j]!=-1&&k-j>=0)
f[i][j][k]=max(f[i][j][k],f[i+1][v][k-j]);
// f[i][j].w=f[i-1][j].w+f[i-1][j+1].w+1;
// f[i][j][0][k]=max(f[i-1][j][0][k],f[i-1][j][0][k]);
// printf("f[%d][%d]=%d ",i,j,f[i][j].s);
// printf("f[%d][%d]=%d\n",i,j,f[i][j].w);
// printf("f[%d][%d][0][%d]=%d\n",i,j,k,f[i][j][0][k]);
for (v=1;v<=j;v++)
f[i][j][k]+=a[v][i];
ans=max(ans,f[i][j][k]);
}
printf("%d",ans);
}