• codevs1257 打砖块


    题目描述 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

     

    正解:DP

    解题报告:

      今天一班选拔赛三试,T2就是这道题,我在考场上想了+调试了2个小时才切掉了,还拍了下才确保AC的。

      f[i][j][k]表示第i列取前j行总共取了k个的最优值。为什么设计这样的状态呢?显然按行DP的话要考虑约束条件很不好做,按列做的话就会好处理一些,并且从右往左做可以避免重复计算(待会儿说)。

      首先我们可以明确如果我们选了一个点相当于是选了一个三角形,在按列摆出的图中靠左对齐的情况下其实就是选取了一个等腰直角三角形。那么我们就可以DP了,我们对于当前列的每一行都考虑从右边的哪些行转移过来。因为不能算重复,所以答案贡献只能加上当前列的自下往上前缀和再加上右边的可选的最优值(不会重叠)。所以我们做到第i列第j行时就只能选取i-1列的j-1行到i-1行作为可转移对象(如果小于j-1的话就会导致被当前三角形覆盖)。另外如果当前这一列一个都不选的话呢?那就不妨从0开始枚举j(行的坐标),这样就可以了。注意下边界条件。

      

     1 //It is made by jump~
     2 #include <iostream>
     3 #include <cstdlib>
     4 #include <cstring>
     5 #include <cstdio>
     6 #include <cmath>
     7 #include <algorithm>
     8 #include <ctime>
     9 #include <vector>
    10 #include <queue>
    11 #include <map>
    12 #include <set>
    13 #ifdef WIN32   
    14 #define OT "%I64d"
    15 #else
    16 #define OT "%lld"
    17 #endif
    18 using namespace std;
    19 typedef long long LL;
    20 const int inf = (1<<20);
    21 const int MAXN = 150;
    22 const int MAXM = 520;
    23 int n,m,ans;
    24 int a[MAXN][MAXN],sum[MAXN][MAXN];
    25 int f[MAXN][MAXN][MAXM];
    26 
    27 inline int getint()
    28 {
    29        int w=0,q=0;
    30        char c=getchar();
    31        while((c<'0' || c>'9') && c!='-') c=getchar();
    32        if (c=='-')  q=1, c=getchar();
    33        while (c>='0' && c<='9') w=w*10+c-'0', c=getchar();
    34        return q ? -w : w;
    35 }
    36 
    37 inline void work(){
    38     n=getint(); m=getint(); 
    39     for(int i=1;i<=n;i++) 
    40     for(int j=n;j>=i;j--) 
    41         a[j][i]=getint();
    42     for(int i=1;i<=n;i++) for(int j=1;j<=i;j++) sum[i][j]=sum[i][j-1]+a[i][j];
    43     for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) for(int k=0;k<=m;k++) f[i][j][k]=-inf;
    44     //f[1][1][1]=a[1][1]; ans=a[1][1];  //for(int i=1;i<=n;i++) for(int j=1;j<=i;j++) f[i][j][0]=0; 
    45     f[0][0][0]=0;
    46 
    47     for(int i=1;i<=n;i++) 
    48     {
    49         for(int j=0;j<=i;j++) 
    50         {         
    51             for(int k=j;k<=m;k++) 
    52             {
    53                 for(int l=max(j-1,0);l<i;l++) 
    54                 {                    
    55                     f[i][j][k]=max(f[i-1][l][k-j]+sum[i][j],f[i][j][k]);                    
    56                 }
    57                 ans=max(ans,f[i][j][k]);
    58             }
    59         }
    60     }
    61     printf("%d",ans);
    62 }
    63 
    64 int main()
    65 {
    66   work();
    67   return 0;
    68 }
  • 相关阅读:
    快速整理sql表结构到wiki
    mac subline批量处理行
    iphone7忘记手机屏幕密码
    docker 常用命令
    初窥响应式布局
    用jquery写的一个图片轮播插件
    javascript中的对象和创建对象的主要模式
    用户注册界面(带js特效)
    用javascript实现简易留言板
    用javascript实现的购物车实例
  • 原文地址:https://www.cnblogs.com/ljh2000-jump/p/5772882.html
Copyright © 2020-2023  润新知