*点击

[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$ 题;

强化版请见 [USACO16OPEN]262144

我们可以设 $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\n",ans);//输出
    //return 0; 
}

 

 

posted @ 2020-08-26 18:11  木偶人-怪咖  阅读(125)  评论(0编辑  收藏  举报
*访客位置3D地图 *目录