zoukankan      html  css  js  c++  java
  • [USACO16OPEN]248

    题目

    Description

    Bessie likes downloading games to play on her cell phone, even though she doesfind the small touch screen rather cumbersome to use with her large hooves.

    She is particularly intrigued by the current game she is playing.The game starts with a sequence of N positive integers (2N248), each in the range 140. In one move, Bessie cantake two adjacent numbers with equal values and replace them a singlenumber of value one greater (e.g., she might replace two adjacent 7swith an 8). The goal is to maximize the value of the largest numberpresent in the sequence at the end of the game. Please help Bessiescore as highly as possible!

    给定一个1*n的地图,在里面玩2048,每次可以合并相邻两个(数值范围1-40),问最大能合出多少。注意合并后的数值并非加倍而是+1,例如2与2合并后的数值为3。

    Input

    The first line of input contains N, and the next N lines give the sequence

    of N numbers at the start of the game.

    Output

    Please output the largest integer Bessie can generate.

    Sample Input

    4
    1
    1
    1
    2

    Sample Output

    3

    Hint

    In this example shown here, Bessie first merges the second and third 1s to

    obtain the sequence 1 2 2, and then she merges the 2s into a 3. Note that it is

    not optimal to join the first two 1s.


    思路

    这是一道有点不错的区间$dp$ 题;

    我们可以设 $dp[i][j]$ 表示可以合成的 区间$[i,j]$ 合成的最大值;

    注意是表示可以合成的区间;

    比如样例 : $1, ~1,~1,~2$ ;

    可合成的区间是 $[1,2]$,而 $[3,4]$ 就不是一个可合成的区间,因为其中是不同的,要求是相同的值则可合成;

    可合成的区间要求这个区间定是通过不断合成,能剩下一个数;

    那么这样转移方程就好写了;

    由于博主过于蒟蒻,一开始设的 $dp[i][j]$ ,表示所有的区间,然后一直考虑数字的位置相邻怎么解决,后来脑子才开窍,换成这种思路;

    那么设成可合成的区间,就不需要考虑相邻怎么解决;

    我们只需要在转移的时候判断, $dp[i][k]$ 等于 $dp[k+1][j]$ 时转移 ;

    还要注意的是,我们设的 $dp[i][j]$ 是可合成的区间,那么不可合成的区间的值就不会被更新,所以我们还需判断 $dp[i][k]$ 和 $dp[k+1][j]$ 都不为 $0$ ;

    那么转移方程就是

    $dp[i][j]=max(dp[i][j],dp[i][k]+1)$ ;

    这样就 $ok$ 了;

    代码

    #include<bits/stdc++.h>
    #define re register
    typedef long long ll;
    using namespace std;
    inline ll read()
    {
        ll a=0,f=1; char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();}
        while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();}
        return a*f;
    }
    ll n;
    ll dp[300][300];
    int main()
    {
        n=read();
        for(re ll i=1;i<=n;i++)
            dp[i][i]=read();//直接读入 
        for(re ll len=2;len<=n;len++)//枚举区间长度 
        for(re ll i=1;i<=n-len+1;i++)//枚举区间起点 
        {
            ll j=i+len-1;//区间终点 
            for(re ll k=1;k<=n;k++)//枚举区间断点 
            if(dp[i][k]==dp[k+1][j]&&dp[i][k])//判断两区间可以合成 
                dp[i][j]=max(dp[i][j],dp[i][k]+1);//更新答案 
        }
        ll ans=0;
        for(re ll i=1;i<=n;i++)
        for(re ll j=1;j<=n;j++)
            ans=max(ans,dp[i][j]);//统计答案 
        printf("%lld
    ",ans);//输出
        //return 0; 
    }
  • 相关阅读:
    测试sql 查询时间
    C# 数组 ArrayList Array 在C#里把ArrayList转换为Array 或 把Array转换为ArrayList
    DotNet软件开发框架
    C# Socket多线程编程实例
    Yahoo!网站性能最佳体验的34条黄金守则
    最基本的Socket编程(C#)
    完全解决VS2008通过Internet连接VSS2005
    追MM与设计模式的有趣见解
    一个GridView的PagerTemplate
    线程
  • 原文地址:https://www.cnblogs.com/wzx-RS-STHN/p/13566686.html
Copyright © 2011-2022 走看看