1. 程式人生 > >Codevs 1257 打磚塊

Codevs 1257 打磚塊

include desc 輸出 tro logs mat alt codevs hint

1257 打磚塊

http://codevs.cn/problem/1257/

題目描述 Description

在一個凹槽中放置了n層磚塊,最上面的一層有n塊磚,第二層有n-1塊,……最下面一層僅有一塊磚。第i層的磚塊從左至右編號為1,2,……i,第i層的第j塊磚有一個價值a[i,j](a[i,j]<=50)。下面是一個有5層磚塊的例子。如果你要敲掉第i層的第j塊磚的話,若i=1,你可以直接敲掉它,若i>1,則你必須先敲掉第i-1層的第j和第j+1塊磚。

你的任務是從一個有n(n<=50)層的磚塊堆中,敲掉(m<=500)塊磚,使得被敲掉的這些磚塊的價值總和最大。

技術分享 輸入描述 Input Description

你將從文件中讀入數據,數據的第一行為兩個正整數,分別表示n,m,接下來的第i每行有n-i+1個數據,分別表示a[i,1],a[i,2]……a[i,n – i + 1]。

輸出描述 Output Description

輸出文件中僅有一個正整數,表示被敲掉磚塊的最大價值總和。

樣例輸入 Sample Input

4 5

2 2 3 4

8 2 7

2 3

49

樣例輸出 Sample Output

19

數據範圍及提示 Data Size & Hint

敲掉第一層的四塊磚,再敲掉第二層的第一塊磚,2+2+3+4+8=19

算法:考慮每一列的情況

    1. dp到第i列,這一列挖j個磚頭,已經挖了s塊:f[i][j][s]
    2. 則可以得出狀態轉移方程
    3. f[i][j][s]=max(f[i-1][l][s-j]) (0<=l<=j+1)
    4. 舉個例子,如果n=5,即有5列,挖的情況從第一列到第五列可以是
    5. 32121或54321。。。。。。
    6. (第i+1列的磚數)大於等於(第i列的磚數-1)
#include <cstdio>
#include 
<iostream> using namespace std; int n,m,a[51][51],f[51][51][501]; int main(){ cin>>n>>m; for(int i=1;i<=n;i++) for(int j=1;j<=n-i+1;j++){ cin>>a[i][j]; a[i][j]+=a[i-1][j]; } for(int i=1;i<=n+1;i++)//第i列 for(int j=0;j<=n+1-i;j++)//挖j個磚頭 for(int k=0;k<=j+1;k++)//上一列的磚頭數 for(int s=j;s<=m;s++)//已經挖了s塊磚頭 f[j][i][s]=max(f[j][i][s],f[k][i-1][s-j]+a[j][i]); cout<<max(f[1][n][m],f[0][n+1][m]); }

Codevs 1257 打磚塊