zoukankan      html  css  js  c++  java
  • sss

    <更新提示>

    <第一次更新>


    <正文>

    Blocks

    Description

    Some of you may have played a game called 'Blocks'. There are n blocks in a row, each box has a color. Here is an example: Gold, Silver, Silver, Silver, Silver, Bronze, Bronze, Bronze, Gold. The corresponding picture will be as shown below:

    If some adjacent boxes are all of the same color, and both the box to its left(if it exists) and its right(if it exists) are of some other color, we call it a 'box segment'. There are 4 box segments. That is: gold, silver, bronze, gold. There are 1, 4, 3, 1 box(es) in the segments respectively.

    Every time, you can click a box, then the whole segment containing that box DISAPPEARS. If that segment is composed of k boxes, you will get kk points. for example, if you click on a silver box, the silver segment disappears, you got 44=16 points.

    Now let's look at the picture below:

    The first one is OPTIMAL.

    Find the highest score you can get, given an initial state of this game.

    题意:通过点击某一颜色消除相邻的所有的这种颜色,得分为len*len,求最大分

    Input Format

    第一行为一个整数 N。

    第二行为 A1,A2,…,AN。

    Output Format

    一行一个整数,代表最大价值。

    Sample Input

    9
    1 2 2 2 2 3 3 3 1
    

    Sample Output

    29
    

    解析

    这种区间操作类的最优解问题显然是区间(dp),不过这道题的状态有点棘手。

    对于一次消除操作,可能会带来左右两边原本不相邻的部分合并带来的影响,所以通常来说的状态是不行了。我们考虑设计一种状态能够记录这种合并带来的影响:设(f[l][r][k])代表区间消除([l,r]),序列后面通过消除操作使得有(k)个颜色为(a[r])的块跟在区间([l,r])后面的最大得分。

    考虑转移,显然,我们可以直接将后面跟着的(k)个块和第(r)个块连在一起消掉,这是一种转移方式。还有就是我们可以在区间([l,r-1])中枚举一个颜色与(a[r])相同的点(i),然后将区间([i+1,r-1])作为一个子问题直接消去,这样就使得(a[r])加入后面跟着的(k)个块中,(i)成为右端点,利用这个状态转移即可。

    至于如何枚举区间内和(a[r])颜色相同的点呢?这是可以预处理直接向前查找的。

    (Code:)

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 220;
    int n,a[N],pre[N],last[N];
    int f[N][N][N];
    inline void input(void)
    {
        scanf("%d",&n);
        for (int i=1;i<=n;i++)
            scanf("%d",&a[i]);
    }
    inline void init(void)
    {
        for (int i=1;i<=n;i++)
        {
            pre[i] = last[a[i]];
            last[a[i]] = i;
        }
    }
    inline int dp(int l,int r,int k)
    {
        if ( l > r ) return 0;
        if ( f[l][r][k] ) return f[l][r][k];
        f[l][r][k] = dp( l , r-1 , 0 ) + (k+1) * (k+1);
        for (int i=pre[r];i>=l;i=pre[i])
            f[l][r][k] = max( f[l][r][k] , dp( l , i , k+1 ) + dp( i+1 , r-1 , 0 ) );
        return f[l][r][k];
    }
    int main(void)
    {
        input();
        init();
        memset( f , 0 , sizeof f );
        dp( 1 , n , 0 );
        printf("%d
    ",f[1][n][0]);
        return 0;
    }
    

    <后记>

  • 相关阅读:
    java获取当前类的路径
    oracle 报错 column ambiguously defined
    各种在线api地址
    双击打开我的电脑 看不到硬盘盘符出现慢 安装百度云之后我的电脑卡
    Tomcat下获取当前类的路径中含有空格的解决方案
    win8解压版Tomcat startup.bat一闪而过的解决办法
    Shell基础篇shell简介之bash编程之参数说明
    Shell 基础篇介绍几个shell程序设计小知识
    Oracle数据仓库的分层管理器解决方案
    DataStage在RedHat Linux Enterprise 3上安装详细步骤(三)
  • 原文地址:https://www.cnblogs.com/Parsnip/p/10999917.html
Copyright © 2011-2022 走看看