[USACO16OPEN]248 G

题目:

题目描述

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 NNN positive integers (2≤N≤2482 \leq N\leq 2482≤N≤248), each in the range 1…401 \ldots 401…40. 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。

输入格式

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

of NNN numbers at the start of the game.

输出格式

Please output the largest integer Bessie can generate.

输入输出样例

输入 #1

4

1

1

1

2

输出 #1

3

说明/提示

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割点合并。

代码实现如下:

  1. /*#!/bin/sh
  2. dir=$GEDIT_CURRENT_DOCUMENT_DIR
  3. name=$GEDIT_CURRENT_DOCUMENT_NAME
  4. pre=${name%.*}
  5. g++ -O2 $dir/$name -o $pre -g -Wall -std=c++11
  6. if test $? -eq 0; then
  7. gnome-terminal -x bash -c "time $dir/$pre;echo;read;"
  8. fi*/
  9. #include<cstdio>
  10. #include<iostream>
  11. #include<algorithm>
  12. #include<cstring>
  13. #include<cmath>
  14. using namespace std;
  15. const int maxn=505,INF=0x3f3f3f3f;
  16. int n,f[2][maxn][maxn],a[maxn],m,ans;//1左0右
  17. inline int read(){
  18. int s=0,w=1;
  19. char ch=getchar();
  20. while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
  21. while(ch>='0'&&ch<='9')s=s*10+ch-'0',ch=getchar();
  22. return s*w;
  23. }
  24. int main(){
  25. n=read();
  26. for(int i=1;i<=n;i++){a[i]=read(),f[0][i][i]=f[1][i][i]=a[i],ans=max(ans,a[i]);}//预处理f[0][i][i]和f[1][i][i]
  27. for(int i=1;i<n;i++){
  28. if(a[i]==a[i+1])f[0][i][i+1]=f[1][i][i+1]=a[i]+1;//相等合并
  29. else f[0][i][i+1]=a[i+1],f[1][i][i+1]=a[i];
  30. ans=max(ans,max(f[0][i][i+1],f[1][i][i+1]));
  31. //cout<<i<<" "<<i+1<<" "<<f[0][i][i+1]<<endl;
  32. }//预处理f[0][i][i+1]和f[1][i][i+1]
  33. for(int d=3;d<=n;d++){
  34. for(int i=1,j;(j=i+d-1)<=n;i++){
  35. if(f[0][i][j-1]==a[j])f[0][i][j]=a[j]+1;//能合并就合并
  36. else f[0][i][j]=a[j];//不能合并要改为最右端的数否则无法继续向右合并
  37. if(f[1][i+1][j]==a[i])f[1][i][j]=a[i]+1;//同理
  38. else f[1][i][j]=a[i];
  39. ans=max(ans,max(f[1][i][j],f[0][i][j]));
  40. //cout<<i<<" "<<j<<" "<<f[0][i][j]<<endl;
  41. }
  42. }//向右向左合并预处理
  43. for(int d=2;d<=n;d++){//左右合并
  44. for(int i=1,j;(j=i+d-1)<=n;i++){
  45. for(int k=i;k<j;k++){
  46. if(f[0][i][k]==f[1][k+1][j])f[0][i][j]=f[1][i][j]=f[0][i][k]+1;//两个区间内的数值相等就可以合并,因为保证了断点左右数值一定代表左右区间的数值,这也是用两个状态的原因
  47. // else f[0][i][j]=f[]
  48. ans=max(ans,max(f[1][i][j],f[0][i][j]));
  49. }
  50. }
  51. }
  52. cout<<ans;
  53. }

调了二十分钟扔了,望有缘人能调出来。

后来康了一眼题解发现想多了。其实不用两个状态,而且只用上面代码的最后一个合并就行

断点左右区间数值相等就合并,价值+1,否则就为0

代码:

  1. /*#!/bin/sh
  2. dir=$GEDIT_CURRENT_DOCUMENT_DIR
  3. name=$GEDIT_CURRENT_DOCUMENT_NAME
  4. pre=${name%.*}
  5. g++ -O2 $dir/$name -o $pre -g -Wall -std=c++11
  6. if test $? -eq 0; then
  7. gnome-terminal -x bash -c "time $dir/$pre;echo;read;"
  8. fi*/
  9. #include<cstdio>
  10. #include<iostream>
  11. #include<algorithm>
  12. #include<cstring>
  13. #include<cmath>
  14. using namespace std;
  15. const int maxn=505,INF=0x3f3f3f3f;
  16. int n,f[maxn][maxn],a[maxn],m,ans;//f[i][j]表示合并i-j的价值,当然如果i-j内不能合并,就为0,例如样例中f[3][4]=0
  17. inline int read(){
  18. int s=0,w=1;
  19. char ch=getchar();
  20. while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
  21. while(ch>='0'&&ch<='9')s=s*10+ch-'0',ch=getchar();
  22. return s*w;
  23. }
  24. int main(){
  25. //freopen("a.in","r",stdin);
  26. n=read();
  27. for(int i=1;i<=n;i++){a[i]=read(),f[i][i]=a[i],ans=max(ans,a[i]);}
  28. for(int i=1;i<n;i++){
  29. if(a[i]==a[i+1])f[i][i+1]=a[i]+1;
  30. // else f[i][i+1]=0;
  31. ans=max(ans,f[i][i+1]);
  32. //cout<<i<<" "<<i+1<<" "<<f[0][i][i+1]<<endl;
  33. }//预处理一模一样
  34. for(int d=2;d<=n;d++){
  35. for(int i=1,j;(j=i+d-1)<=n;i++){
  36. for(int k=i;k<j;k++){//有k+1右端点肯定不能超过j
  37. if(f[i][k]==f[k+1][j]&&f[i][k]!=0)f[i][j]=f[i][k]+1;//如果两个区间i-k和k+1-j内的数值相同,那就合并。
  38. //但是有一要求:两个区间内的数值不能为0,即两个区间必须本身能合并
  39. ans=max(ans,f[i][j]);
  40. }
  41. //cout<<i<<" "<<j<<" "<<f[i][j]<<endl;
  42. }
  43. }
  44. cout<<ans;
  45. }

over~

「区间DP」「洛谷PP3146 」[USACO16OPEN]248 G的更多相关文章

  1. 区间dp 能量项链 洛谷p1063

    题目大意:如果前一颗能量珠的头标记为m,尾标记为r,后一颗能量珠的头标记为r,尾标记为n,则聚合后释放的能量为 (Mars单位),新产生的珠子的头标记为m,尾标记为n. 需要时,Mars人就用吸盘夹住 ...

  2. 「区间DP」「洛谷P1043」数字游戏

    「洛谷P1043」数字游戏 日后再写 代码 /*#!/bin/sh dir=$GEDIT_CURRENT_DOCUMENT_DIR name=$GEDIT_CURRENT_DOCUMENT_NAME ...

  3. 「区间DP」「洛谷P3205」「 [HNOI2010]」合唱队

    洛谷P3205 [HNOI2010]合唱队 题目: 题目描述 为了在即将到来的晚会上有更好的演出效果,作为 A 合唱队负责人的小 A 需要将合唱队的人根据他们的身高排出一个队形.假定合唱队一共 n 个 ...

  4. 「洛谷5017」「NOIP2018」摆渡车【DP,经典好题】

    前言 在考场被这个题搞自闭了,那个时候自己是真的太菜了.qwq 现在水平稍微高了一点,就过来切一下这一道\(DP\)经典好题. 附加一个题目链接:[洛谷] 正文 虽然题目非常的简短,但是解法有很多. ...

  5. Solution -「APIO 2016」「洛谷 P3643」划艇

    \(\mathcal{Description}\)   Link & 双倍经验.   给定 \(n\) 个区间 \([a_i,b_i)\)(注意原题是闭区间,这里只为方便后文描述),求 \(\ ...

  6. 「洛谷3870」「TJOI2009」开关【线段树】

    题目链接 [洛谷] 题解 来做一下水题来掩饰ZJOI2019考炸的心情QwQ. 很明显可以线段树. 维护两个值,\(Lazy\)懒标记表示当前区间是否需要翻转,\(s\)表示区间还有多少灯是亮着的. ...

  7. 「洛谷5283」「LOJ3048」「十二省联考2019」异或粽子【可持久化01trie+优先队列】

    题目链接 [洛谷传送门] [LOJ传送门] 题目大意 让你求区间异或和前\(k\)大的异或和的和. 正解 这道题目是Blue sky大佬教我做的(祝贺bluesky大佬进HA省A队) 我们做过某一些题 ...

  8. Solution -「洛谷 P4372」Out of Sorts P

    \(\mathcal{Description}\)   OurOJ & 洛谷 P4372(几乎一致)   设计一个排序算法,设现在对 \(\{a_n\}\) 中 \([l,r]\) 内的元素排 ...

  9. 「洛谷4197」「BZOJ3545」peak【线段树合并】

    题目链接 [洛谷] [BZOJ]没有权限号嘤嘤嘤.题号:3545 题解 窝不会克鲁斯卡尔重构树怎么办??? 可以离线乱搞. 我们将所有的操作全都存下来. 为了解决小于等于\(x\)的操作,那么我们按照 ...

随机推荐

  1. 团体天梯赛L1-041.寻找250

    对方不想和你说话,并向你扔了一串数…… 而你必须从这一串数字中找到“250”这个高大上的感人数字. 输入格式: 输入在一行中给出不知道多少个绝对值不超过1000的整数,其中保证至少存在一个“250”. ...

  2. 来看看阿里架构师Java 代码打日志姿势!你也是这样写的吗

    使用slf4j 使用门面模式的日志框架,有利于维护和各个类的日志处理方式统一. 实现方式统一使用: Logback框架 打日志的正确方式 什么时候应该打日志 当你遇到问题的时候,只能通过debug功能 ...

  3. Centos 7 k8s Deployment新副本控制器

    一.概念 Kubernetes提供了一种更加简单的更新RC和Pod的机制,叫做Deployment.通过在Deployment中描述你所期望的集群状态,Deployment Controller会将在 ...

  4. SpringColud Eureka的服务注册与发现

    一.Eureka简介 本文中所有代码都会上传到git上,请放心浏览 项目git地址:https://github.com/839022478/Spring-Cloud 在传统应用中,组件之间的调用,通 ...

  5. Asp.Net Mvc 控制器详解

    理解控制器 控制器的角色 (1)中转作用:控制器通过前面的学习大家应该知道它是一个承上启下的作用,根据用户输入,执行响应行为(动 作方法),同时在行为中调用模型的业务逻辑,返回给用户结果(视图). ( ...

  6. Python绘图之Turtle库详解(1)

    Turtle库是Python语言中一个很流行的绘制图像的函数库,想象一个小乌龟,在一个横轴为x.纵轴为y的坐标系原点,(0,0)位置开始,它根据一组函数指令的控制,在这个平面坐标系中移动,从而在它爬行 ...

  7. linux配置SVN服务

    在linux下配置SVN库,网上找到不少教程,但是对于有几个容易混淆的地方需要记录下, 1.在创建SVN文档库的时候,需要使用svn命令先创建出来, svnadmin create /home/svn ...

  8. vim改变字体和查看映射的(mapping)命令

    临时修改.通过gvim Command MODE,输入如下命令即可: Linux/Unix: set guifont=Monospace\空格14 注意这里需要对空格使用\进行转义 Windows:  ...

  9. sockaddr_in与sockaddr区别

    先粘代码 struct sockaddr { __SOCKADDR_COMMON (sa_); /* Common data: address family and length. */ char s ...

  10. WeChair项目Alpha冲刺(3/10)

    团队项目进行情况 1.昨日进展    Alpha冲刺第三天 昨日进展: 前端初步完成小程序预约页的html+css设计 后端springboot项目测试运行HelloWorld通过,以及LoginCo ...